2 Unix SMB/CIFS implementation.
3 client connect/disconnect routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Andrew Bartlett 2001-2003
6 Copyright (C) Volker Lendecke 2011
7 Copyright (C) Jeremy Allison 2011
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "libsmb/libsmb.h"
25 #include "auth_info.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../libcli/auth/spnego.h"
29 #include "auth/credentials/credentials.h"
30 #include "auth/gensec/gensec.h"
31 #include "auth/ntlmssp/ntlmssp.h"
32 #include "auth_generic.h"
33 #include "libads/kerberos_proto.h"
35 #include "../lib/util/tevent_ntstatus.h"
36 #include "async_smb.h"
37 #include "libsmb/nmblib.h"
38 #include "librpc/ndr/libndr.h"
39 #include "../libcli/smb/smbXcli_base.h"
40 #include "lib/param/param.h"
42 #define STAR_SMBSERVER "*SMBSERVER"
44 static struct cli_credentials *cli_session_creds_init(TALLOC_CTX *mem_ctx,
50 bool fallback_after_kerberos,
52 bool password_is_nt_hash)
54 struct loadparm_context *lp_ctx = NULL;
55 struct cli_credentials *creds = NULL;
58 creds = cli_credentials_init(mem_ctx);
63 lp_ctx = loadparm_init_s3(creds, loadparm_s3_helpers());
67 cli_credentials_set_conf(creds, lp_ctx);
73 if (username == NULL) {
77 if (strlen(username) == 0) {
78 if (password != NULL && strlen(password) == 0) {
80 * some callers pass "" as no password
82 * gensec only handles NULL as no password.
86 if (password == NULL) {
87 cli_credentials_set_anonymous(creds);
92 if (use_kerberos && fallback_after_kerberos) {
93 cli_credentials_set_kerberos_state(creds,
94 CRED_AUTO_USE_KERBEROS);
95 } else if (use_kerberos) {
96 cli_credentials_set_kerberos_state(creds,
97 CRED_MUST_USE_KERBEROS);
99 cli_credentials_set_kerberos_state(creds,
100 CRED_DONT_USE_KERBEROS);
106 features = cli_credentials_get_gensec_features(creds);
107 features |= GENSEC_FEATURE_NTLM_CCACHE;
108 cli_credentials_set_gensec_features(creds, features);
110 if (password != NULL && strlen(password) == 0) {
112 * some callers pass "" as no password
114 * GENSEC_FEATURE_NTLM_CCACHE only handles
115 * NULL as no password.
121 ok = cli_credentials_set_username(creds,
128 ok = cli_credentials_set_domain(creds,
136 ok = cli_credentials_set_realm(creds,
144 if (password != NULL && strlen(password) > 0) {
145 if (password_is_nt_hash) {
146 struct samr_Password nt_hash;
149 converted = strhex_to_str((char *)nt_hash.hash,
150 sizeof(nt_hash.hash),
153 if (converted != sizeof(nt_hash.hash)) {
157 ok = cli_credentials_set_nt_hash(creds,
164 ok = cli_credentials_set_password(creds,
179 /********************************************************
180 Utility function to ensure we always return at least
181 a valid char * pointer to an empty string for the
182 cli->server_os, cli->server_type and cli->server_domain
184 *******************************************************/
186 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
193 *destlen = clistr_pull_talloc(mem_ctx,
200 if (*destlen == -1) {
201 return NT_STATUS_NO_MEMORY;
205 *dest = talloc_strdup(mem_ctx, "");
207 return NT_STATUS_NO_MEMORY;
213 /****************************************************************************
214 Work out suitable capabilities to offer the server.
215 ****************************************************************************/
217 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
218 uint32_t sesssetup_capabilities)
220 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
223 * We only send capabilities based on the mask for:
224 * - client only flags
225 * - flags used in both directions
227 * We do not echo the server only flags, except some legacy flags.
229 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
230 * CAP_LARGE_WRITEX in order to allow us to do large reads
231 * against old Samba releases (<= 3.6.x).
233 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
236 * Session Setup specific flags CAP_DYNAMIC_REAUTH
237 * and CAP_EXTENDED_SECURITY are passed by the caller.
238 * We need that in order to do guest logins even if
239 * CAP_EXTENDED_SECURITY is negotiated.
241 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
242 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
243 client_capabilities |= sesssetup_capabilities;
245 return client_capabilities;
248 /****************************************************************************
249 Do a NT1 guest session setup.
250 ****************************************************************************/
252 struct cli_session_setup_guest_state {
253 struct cli_state *cli;
258 static void cli_session_setup_guest_done(struct tevent_req *subreq);
260 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
261 struct tevent_context *ev,
262 struct cli_state *cli,
263 struct tevent_req **psmbreq)
265 struct tevent_req *req, *subreq;
266 struct cli_session_setup_guest_state *state;
270 req = tevent_req_create(mem_ctx, &state,
271 struct cli_session_setup_guest_state);
278 SCVAL(vwv+0, 0, 0xFF);
281 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
283 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
284 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
289 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
291 bytes = talloc_array(state, uint8_t, 0);
293 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
295 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
297 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
298 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
305 state->bytes.iov_base = (void *)bytes;
306 state->bytes.iov_len = talloc_get_size(bytes);
308 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 0, 13,
309 vwv, 1, &state->bytes);
310 if (subreq == NULL) {
314 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
319 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
320 struct tevent_context *ev,
321 struct cli_state *cli)
323 struct tevent_req *req, *subreq;
326 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
331 status = smb1cli_req_chain_submit(&subreq, 1);
332 if (!NT_STATUS_IS_OK(status)) {
333 tevent_req_nterror(req, status);
334 return tevent_req_post(req, ev);
339 static void cli_session_setup_guest_done(struct tevent_req *subreq)
341 struct tevent_req *req = tevent_req_callback_data(
342 subreq, struct tevent_req);
343 struct cli_session_setup_guest_state *state = tevent_req_data(
344 req, struct cli_session_setup_guest_state);
345 struct cli_state *cli = state->cli;
356 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
359 if (!NT_STATUS_IS_OK(status)) {
360 tevent_req_nterror(req, status);
364 inhdr = in + NBT_HDR_SIZE;
367 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
368 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
370 status = smb_bytes_talloc_string(cli,
377 if (!NT_STATUS_IS_OK(status)) {
378 tevent_req_nterror(req, status);
383 status = smb_bytes_talloc_string(cli,
390 if (!NT_STATUS_IS_OK(status)) {
391 tevent_req_nterror(req, status);
396 status = smb_bytes_talloc_string(cli,
403 if (!NT_STATUS_IS_OK(status)) {
404 tevent_req_nterror(req, status);
409 tevent_req_done(req);
412 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
414 return tevent_req_simple_recv_ntstatus(req);
417 /* The following is calculated from :
419 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
420 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
424 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
426 struct cli_sesssetup_blob_state {
427 struct tevent_context *ev;
428 struct cli_state *cli;
430 uint16_t max_blob_size;
433 struct iovec *recv_iov;
436 const uint8_t *inbuf;
443 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
444 struct tevent_req **psubreq);
445 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
447 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
448 struct tevent_context *ev,
449 struct cli_state *cli,
452 struct tevent_req *req, *subreq;
453 struct cli_sesssetup_blob_state *state;
454 uint32_t usable_space;
456 req = tevent_req_create(mem_ctx, &state,
457 struct cli_sesssetup_blob_state);
465 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
466 usable_space = UINT16_MAX;
468 usable_space = cli_state_available_size(cli,
469 BASE_SESSSETUP_BLOB_PACKET_SIZE);
472 if (usable_space == 0) {
473 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
474 "(not possible to send %u bytes)\n",
475 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
476 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
477 return tevent_req_post(req, ev);
479 state->max_blob_size = MIN(usable_space, 0xFFFF);
481 if (!cli_sesssetup_blob_next(state, &subreq)) {
482 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
483 return tevent_req_post(req, ev);
485 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
489 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
490 struct tevent_req **psubreq)
492 struct tevent_req *subreq;
495 thistime = MIN(state->blob.length, state->max_blob_size);
497 state->this_blob.data = state->blob.data;
498 state->this_blob.length = thistime;
500 state->blob.data += thistime;
501 state->blob.length -= thistime;
503 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
504 subreq = smb2cli_session_setup_send(state, state->ev,
507 state->cli->smb2.session,
509 SMB2_CAP_DFS, /* in_capabilities */
511 0, /* in_previous_session_id */
513 if (subreq == NULL) {
517 uint16_t in_buf_size = 0;
518 uint16_t in_mpx_max = 0;
519 uint16_t in_vc_num = 0;
520 uint32_t in_sess_key = 0;
521 uint32_t in_capabilities = 0;
522 const char *in_native_os = NULL;
523 const char *in_native_lm = NULL;
525 in_buf_size = CLI_BUFFER_SIZE;
526 in_mpx_max = smbXcli_conn_max_requests(state->cli->conn);
527 in_vc_num = cli_state_get_vc_num(state->cli);
528 in_sess_key = smb1cli_conn_server_session_key(state->cli->conn);
529 in_capabilities = cli_session_setup_capabilities(state->cli,
530 CAP_EXTENDED_SECURITY);
531 in_native_os = "Unix";
532 in_native_lm = "Samba";
535 * For now we keep the same values as before,
536 * we may remove these in a separate commit later.
542 subreq = smb1cli_session_setup_ext_send(state, state->ev,
545 state->cli->smb1.pid,
546 state->cli->smb1.session,
555 if (subreq == NULL) {
563 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
565 struct tevent_req *req = tevent_req_callback_data(
566 subreq, struct tevent_req);
567 struct cli_sesssetup_blob_state *state = tevent_req_data(
568 req, struct cli_sesssetup_blob_state);
569 struct cli_state *cli = state->cli;
572 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
573 status = smb2cli_session_setup_recv(subreq, state,
577 status = smb1cli_session_setup_ext_recv(subreq, state,
581 &state->out_native_os,
582 &state->out_native_lm);
585 if (!NT_STATUS_IS_OK(status)
586 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
587 tevent_req_nterror(req, status);
591 if (cli->server_os == NULL) {
592 cli->server_os = talloc_move(cli, &state->out_native_os);
594 if (cli->server_type == NULL) {
595 cli->server_type = talloc_move(cli, &state->out_native_lm);
598 state->status = status;
600 if (state->blob.length != 0) {
604 if (!cli_sesssetup_blob_next(state, &subreq)) {
608 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
611 tevent_req_done(req);
614 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
617 const uint8_t **pinbuf,
618 struct iovec **precv_iov)
620 struct cli_sesssetup_blob_state *state = tevent_req_data(
621 req, struct cli_sesssetup_blob_state);
623 struct iovec *recv_iov;
625 if (tevent_req_is_nterror(req, &status)) {
626 TALLOC_FREE(state->cli->smb2.session);
627 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
628 tevent_req_received(req);
632 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
634 *pblob = state->ret_blob;
636 if (pinbuf != NULL) {
637 *pinbuf = state->inbuf;
639 if (precv_iov != NULL) {
640 *precv_iov = recv_iov;
642 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
643 status = state->status;
644 tevent_req_received(req);
648 /****************************************************************************
649 Use in-memory credentials cache
650 ****************************************************************************/
652 static void use_in_memory_ccache(void) {
653 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
656 /****************************************************************************
657 Do a spnego/NTLMSSP encrypted session setup.
658 ****************************************************************************/
660 struct cli_session_setup_gensec_state {
661 struct tevent_context *ev;
662 struct cli_state *cli;
663 struct auth_generic_state *auth_generic;
666 const uint8_t *inbuf;
667 struct iovec *recv_iov;
671 DATA_BLOB session_key;
674 static int cli_session_setup_gensec_state_destructor(
675 struct cli_session_setup_gensec_state *state)
677 TALLOC_FREE(state->auth_generic);
678 data_blob_clear_free(&state->session_key);
682 static void cli_session_setup_gensec_local_next(struct tevent_req *req);
683 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
684 static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
685 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
686 static void cli_session_setup_gensec_ready(struct tevent_req *req);
688 static struct tevent_req *cli_session_setup_gensec_send(
689 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
690 const char *user, const char *pass, const char *domain,
691 enum credentials_use_kerberos krb5_state,
692 const char *target_service,
693 const char *target_hostname)
695 struct tevent_req *req;
696 struct cli_session_setup_gensec_state *state;
698 const DATA_BLOB *b = NULL;
699 const char *dest_realm = NULL;
700 struct cli_credentials *creds = NULL;
702 req = tevent_req_create(mem_ctx, &state,
703 struct cli_session_setup_gensec_state);
710 talloc_set_destructor(
711 state, cli_session_setup_gensec_state_destructor);
714 * dest_realm is only valid in the winbindd use case,
715 * where we also have the account in that realm.
717 dest_realm = cli_state_remote_realm(cli);
719 creds = cli_session_creds_init(state,
725 cli->fallback_after_kerberos,
728 if (tevent_req_nomem(creds, req)) {
729 return tevent_req_post(req, ev);
732 cli_credentials_set_kerberos_state(creds, krb5_state);
734 status = auth_generic_client_prepare(state, &state->auth_generic);
735 if (tevent_req_nterror(req, status)) {
736 return tevent_req_post(req, ev);
739 status = auth_generic_set_creds(state->auth_generic, creds);
740 if (tevent_req_nterror(req, status)) {
741 return tevent_req_post(req, ev);
744 gensec_want_feature(state->auth_generic->gensec_security,
745 GENSEC_FEATURE_SESSION_KEY);
747 if (target_service != NULL) {
748 status = gensec_set_target_service(
749 state->auth_generic->gensec_security,
751 if (tevent_req_nterror(req, status)) {
752 return tevent_req_post(req, ev);
756 if (target_hostname != NULL) {
757 status = gensec_set_target_hostname(
758 state->auth_generic->gensec_security,
760 if (tevent_req_nterror(req, status)) {
761 return tevent_req_post(req, ev);
765 b = smbXcli_conn_server_gss_blob(cli->conn);
770 state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
772 status = auth_generic_client_start(state->auth_generic,
774 if (tevent_req_nterror(req, status)) {
775 return tevent_req_post(req, ev);
778 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
779 state->cli->smb2.session = smbXcli_session_create(cli,
781 if (tevent_req_nomem(state->cli->smb2.session, req)) {
782 return tevent_req_post(req, ev);
786 cli_session_setup_gensec_local_next(req);
787 if (!tevent_req_is_in_progress(req)) {
788 return tevent_req_post(req, ev);
794 static void cli_session_setup_gensec_local_next(struct tevent_req *req)
796 struct cli_session_setup_gensec_state *state =
798 struct cli_session_setup_gensec_state);
799 struct tevent_req *subreq = NULL;
801 if (state->local_ready) {
802 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
806 subreq = gensec_update_send(state, state->ev,
807 state->auth_generic->gensec_security,
809 if (tevent_req_nomem(subreq, req)) {
812 tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
815 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
817 struct tevent_req *req =
818 tevent_req_callback_data(subreq,
820 struct cli_session_setup_gensec_state *state =
822 struct cli_session_setup_gensec_state);
825 status = gensec_update_recv(subreq, state, &state->blob_out);
827 state->blob_in = data_blob_null;
828 if (!NT_STATUS_IS_OK(status) &&
829 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
831 tevent_req_nterror(req, status);
835 if (NT_STATUS_IS_OK(status)) {
836 state->local_ready = true;
839 if (state->local_ready && state->remote_ready) {
840 cli_session_setup_gensec_ready(req);
844 cli_session_setup_gensec_remote_next(req);
847 static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
849 struct cli_session_setup_gensec_state *state =
851 struct cli_session_setup_gensec_state);
852 struct tevent_req *subreq = NULL;
854 if (state->remote_ready) {
855 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
859 subreq = cli_sesssetup_blob_send(state, state->ev,
860 state->cli, state->blob_out);
861 if (tevent_req_nomem(subreq, req)) {
864 tevent_req_set_callback(subreq,
865 cli_session_setup_gensec_remote_done,
869 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
871 struct tevent_req *req =
872 tevent_req_callback_data(subreq,
874 struct cli_session_setup_gensec_state *state =
876 struct cli_session_setup_gensec_state);
880 TALLOC_FREE(state->recv_iov);
882 status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
883 &state->inbuf, &state->recv_iov);
885 data_blob_free(&state->blob_out);
886 if (!NT_STATUS_IS_OK(status) &&
887 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
889 tevent_req_nterror(req, status);
893 if (NT_STATUS_IS_OK(status)) {
894 struct smbXcli_session *session = NULL;
895 bool is_guest = false;
897 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
898 session = state->cli->smb2.session;
900 session = state->cli->smb1.session;
903 is_guest = smbXcli_session_is_guest(session);
906 * We can't finish the gensec handshake, we don't
907 * have a negotiated session key.
909 * So just pretend we are completely done.
911 * Note that smbXcli_session_is_guest()
912 * always returns false if we require signing.
914 state->blob_in = data_blob_null;
915 state->local_ready = true;
918 state->remote_ready = true;
921 if (state->local_ready && state->remote_ready) {
922 cli_session_setup_gensec_ready(req);
926 cli_session_setup_gensec_local_next(req);
929 static void cli_session_setup_gensec_ready(struct tevent_req *req)
931 struct cli_session_setup_gensec_state *state =
933 struct cli_session_setup_gensec_state);
934 const char *server_domain = NULL;
937 if (state->blob_in.length != 0) {
938 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
942 if (state->blob_out.length != 0) {
943 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
948 * gensec_ntlmssp_server_domain() returns NULL
949 * if NTLMSSP is not used.
951 * We can remove this later
952 * and leave the server domain empty for SMB2 and above
953 * in future releases.
955 server_domain = gensec_ntlmssp_server_domain(
956 state->auth_generic->gensec_security);
958 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
959 TALLOC_FREE(state->cli->server_domain);
960 state->cli->server_domain = talloc_strdup(state->cli,
962 if (state->cli->server_domain == NULL) {
963 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
968 if (state->is_anonymous) {
970 * Windows server does not set the
971 * SMB2_SESSION_FLAG_IS_NULL flag.
973 * This fix makes sure we do not try
974 * to verify a signature on the final
975 * session setup response.
977 tevent_req_done(req);
981 status = gensec_session_key(state->auth_generic->gensec_security,
982 state, &state->session_key);
983 if (tevent_req_nterror(req, status)) {
987 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
988 struct smbXcli_session *session = state->cli->smb2.session;
990 status = smb2cli_session_set_session_key(session,
993 if (tevent_req_nterror(req, status)) {
997 struct smbXcli_session *session = state->cli->smb1.session;
1000 status = smb1cli_session_set_session_key(session,
1001 state->session_key);
1002 if (tevent_req_nterror(req, status)) {
1006 active = smb1cli_conn_activate_signing(state->cli->conn,
1012 ok = smb1cli_conn_check_signing(state->cli->conn,
1015 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1021 tevent_req_done(req);
1024 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1026 struct cli_session_setup_gensec_state *state =
1027 tevent_req_data(req,
1028 struct cli_session_setup_gensec_state);
1031 if (tevent_req_is_nterror(req, &status)) {
1032 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1035 return NT_STATUS_OK;
1038 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1039 const char *principal)
1043 account = talloc_strdup(mem_ctx, principal);
1044 if (account == NULL) {
1047 p = strchr_m(account, '@');
1054 /****************************************************************************
1055 Do a spnego encrypted session setup.
1057 user_domain: The shortname of the domain the user/machine is a member of.
1058 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1059 ****************************************************************************/
1061 struct cli_session_setup_spnego_state {
1065 static void cli_session_setup_spnego_done(struct tevent_req *subreq);
1067 static struct tevent_req *cli_session_setup_spnego_send(
1068 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1069 const char *user, const char *pass, const char *user_domain)
1071 struct tevent_req *req, *subreq;
1072 struct cli_session_setup_spnego_state *state;
1073 const char *user_principal = NULL;
1074 const char *user_account = NULL;
1075 const char *target_hostname = NULL;
1076 const DATA_BLOB *server_blob = NULL;
1077 enum credentials_use_kerberos krb5_state;
1078 bool try_kerberos = false;
1079 bool need_kinit = false;
1081 req = tevent_req_create(mem_ctx, &state,
1082 struct cli_session_setup_spnego_state);
1087 if (user != NULL && strlen(user) != 0) {
1088 user_principal = user;
1089 user_account = cli_session_setup_get_account(state, user);
1090 if (tevent_req_nomem(user_account, req)) {
1091 return tevent_req_post(req, ev);
1094 user_principal = NULL;
1098 target_hostname = smbXcli_conn_remote_name(cli->conn);
1099 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1101 /* the server might not even do spnego */
1102 if (server_blob != NULL && server_blob->length != 0) {
1103 char *principal = NULL;
1104 char *OIDs[ASN1_MAX_OIDS];
1107 /* The server sent us the first part of the SPNEGO exchange in the
1108 * negprot reply. It is WRONG to depend on the principal sent in the
1109 * negprot reply, but right now we do it. If we don't receive one,
1110 * we try to best guess, then fall back to NTLM. */
1111 if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1112 &principal, NULL) ||
1114 state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1115 tevent_req_done(req);
1116 return tevent_req_post(req, ev);
1118 TALLOC_FREE(principal);
1120 /* make sure the server understands kerberos */
1121 for (i = 0; OIDs[i] != NULL; i++) {
1123 DEBUG(3,("got OID=%s\n", OIDs[i]));
1125 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1128 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1129 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1130 cli->got_kerberos_mechanism = True;
1132 talloc_free(OIDs[i]);
1136 if (cli->use_kerberos) {
1137 if (cli->fallback_after_kerberos) {
1138 krb5_state = CRED_AUTO_USE_KERBEROS;
1140 krb5_state = CRED_MUST_USE_KERBEROS;
1143 krb5_state = CRED_DONT_USE_KERBEROS;
1146 if (krb5_state != CRED_DONT_USE_KERBEROS) {
1147 try_kerberos = true;
1150 if (target_hostname == NULL) {
1151 try_kerberos = false;
1152 } else if (is_ipaddress(target_hostname)) {
1153 try_kerberos = false;
1154 } else if (strequal(target_hostname, "localhost")) {
1155 try_kerberos = false;
1156 } else if (strequal(target_hostname, STAR_SMBSERVER)) {
1157 try_kerberos = false;
1158 } else if (user_principal == NULL) {
1159 try_kerberos = false;
1162 if (krb5_state == CRED_MUST_USE_KERBEROS && !try_kerberos) {
1163 DEBUG(0, ("Kerberos auth with '%s' to access '%s' not possible\n",
1164 user_principal, target_hostname));
1165 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1166 return tevent_req_post(req, ev);
1169 if (pass == NULL || strlen(pass) == 0) {
1171 } else if (krb5_state == CRED_MUST_USE_KERBEROS) {
1172 need_kinit = try_kerberos;
1173 } else if (!cli->got_kerberos_mechanism) {
1175 * Most likely the server doesn't support
1176 * Kerberos, don't waste time doing a kinit
1180 need_kinit = try_kerberos;
1186 use_in_memory_ccache();
1187 ret = kerberos_kinit_password(user_principal, pass,
1188 0 /* no time correction for now */,
1192 DEBUG(0, ("Kinit for %s to access %s failed: %s\n",
1193 user_principal, target_hostname,
1194 error_message(ret)));
1195 if (krb5_state == CRED_MUST_USE_KERBEROS) {
1196 state->result = ADS_ERROR_KRB5(ret);
1197 tevent_req_done(req);
1198 return tevent_req_post(req, ev);
1202 * Ignore the error and hope that NTLM will work
1208 subreq = cli_session_setup_gensec_send(state, ev, cli,
1215 if (tevent_req_nomem(subreq, req)) {
1216 return tevent_req_post(req, ev);
1218 tevent_req_set_callback(
1219 subreq, cli_session_setup_spnego_done, req);
1223 static void cli_session_setup_spnego_done(struct tevent_req *subreq)
1225 struct tevent_req *req = tevent_req_callback_data(
1226 subreq, struct tevent_req);
1229 status = cli_session_setup_gensec_recv(subreq);
1230 TALLOC_FREE(subreq);
1231 if (tevent_req_nterror(req, status)) {
1235 tevent_req_done(req);
1238 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1240 struct cli_session_setup_spnego_state *state = tevent_req_data(
1241 req, struct cli_session_setup_spnego_state);
1244 if (tevent_req_is_nterror(req, &status)) {
1245 state->result = ADS_ERROR_NT(status);
1248 return state->result;
1251 struct cli_session_setup_state {
1252 struct cli_state *cli;
1253 uint8_t nt_hash[16];
1254 uint8_t lm_hash[16];
1255 DATA_BLOB apassword_blob;
1256 DATA_BLOB upassword_blob;
1257 DATA_BLOB lm_session_key;
1258 DATA_BLOB session_key;
1259 char *out_native_os;
1260 char *out_native_lm;
1261 char *out_primary_domain;
1264 static void cli_session_setup_cleanup(struct tevent_req *req,
1265 enum tevent_req_state req_state)
1267 struct cli_session_setup_state *state = tevent_req_data(
1268 req, struct cli_session_setup_state);
1270 if (req_state != TEVENT_REQ_RECEIVED) {
1275 * We only call data_blob_clear() as
1276 * some of the blobs point to the same memory.
1278 * We let the talloc hierachy free the memory.
1280 data_blob_clear(&state->apassword_blob);
1281 data_blob_clear(&state->upassword_blob);
1282 data_blob_clear(&state->lm_session_key);
1283 data_blob_clear(&state->session_key);
1284 ZERO_STRUCTP(state);
1287 static void cli_session_setup_done_spnego(struct tevent_req *subreq);
1288 static void cli_session_setup_done_nt1(struct tevent_req *subreq);
1289 static void cli_session_setup_done_lm21(struct tevent_req *subreq);
1291 /****************************************************************************
1292 Send a session setup. The username and workgroup is in UNIX character
1293 format and must be converted to DOS codepage format before sending. If the
1294 password is in plaintext, the same should be done.
1295 ****************************************************************************/
1297 struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
1298 struct tevent_context *ev,
1299 struct cli_state *cli,
1302 const char *workgroup)
1304 struct tevent_req *req, *subreq;
1305 struct cli_session_setup_state *state;
1308 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1309 bool use_spnego = false;
1310 bool do_lmresponse = false;
1311 const char *username = "";
1312 const char *domain = "";
1313 const char *password = "";
1314 DATA_BLOB target_info = data_blob_null;
1315 DATA_BLOB challenge = data_blob_null;
1316 uint16_t in_buf_size = 0;
1317 uint16_t in_mpx_max = 0;
1318 uint16_t in_vc_num = 0;
1319 uint32_t in_sess_key = 0;
1320 const char *in_native_os = NULL;
1321 const char *in_native_lm = NULL;
1323 req = tevent_req_create(mem_ctx, &state,
1324 struct cli_session_setup_state);
1330 tevent_req_set_cleanup_fn(req, cli_session_setup_cleanup);
1333 user2 = talloc_strdup(state, user);
1335 user2 = talloc_strdup(state, "");
1337 if (user2 == NULL) {
1338 tevent_req_oom(req);
1339 return tevent_req_post(req, ev);
1346 /* allow for workgroups as part of the username */
1347 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1348 (p=strchr_m(user2,*lp_winbind_separator()))) {
1351 if (!strupper_m(user2)) {
1352 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1353 return tevent_req_post(req, ev);
1359 * Now work out what sort of session setup we are going to
1360 * do. I have split this into separate functions to make the flow a bit
1361 * easier to understand (tridge).
1363 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
1365 } else if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1367 } else if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
1369 * if the server supports extended security then use SPNEGO
1370 * even for anonymous connections.
1378 subreq = cli_session_setup_spnego_send(
1379 state, ev, cli, user, pass, workgroup);
1380 if (tevent_req_nomem(subreq, req)) {
1381 return tevent_req_post(req, ev);
1383 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
1388 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1390 * SessionSetupAndX was introduced by LANMAN 1.0. So we skip
1391 * this step against older servers.
1393 tevent_req_done(req);
1394 return tevent_req_post(req, ev);
1397 if (user == NULL || strlen(user) == 0) {
1399 * Do an anonymous session setup
1401 goto non_spnego_creds_done;
1404 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
1406 * Do an anonymous session setup,
1407 * the password is passed via the tree connect.
1409 goto non_spnego_creds_done;
1418 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1419 bool use_unicode = smbXcli_conn_use_unicode(cli->conn);
1420 uint8_t *bytes = NULL;
1421 size_t bytes_len = 0;
1422 const char *pw = password;
1428 pw_len = strlen(pw) + 1;
1430 if (!lp_client_plaintext_auth()) {
1431 DEBUG(1, ("Server requested PLAINTEXT password but "
1432 "'client plaintext auth = no'\n"));
1433 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1434 return tevent_req_post(req, ev);
1437 bytes = talloc_array(state, uint8_t, 0);
1438 bytes = trans2_bytes_push_str(bytes, use_unicode,
1439 pw, pw_len, &bytes_len);
1440 if (tevent_req_nomem(bytes, req)) {
1441 return tevent_req_post(req, ev);
1446 * CAP_UNICODE, can only be negotiated by NT1.
1448 state->upassword_blob = data_blob_const(bytes,
1451 state->apassword_blob = data_blob_const(bytes,
1455 goto non_spnego_creds_done;
1458 challenge = data_blob_const(smb1cli_conn_server_challenge(cli->conn), 8);
1459 E_md4hash(password, state->nt_hash);
1461 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1462 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
1464 * Don't send an NTLMv2 response without NTLMSSP if we
1465 * want to use spnego support.
1467 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
1468 " but 'client use spnego = yes'"
1469 " and 'client ntlmv2 auth = yes' is set\n"));
1470 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1471 return tevent_req_post(req, ev);
1474 if (lp_client_ntlmv2_auth()) {
1478 * note that the 'domain' here is a best
1479 * guess - we don't know the server's domain
1480 * at this point. Windows clients also don't
1483 target_info = NTLMv2_generate_names_blob(state,
1486 if (tevent_req_nomem(target_info.data, req)) {
1487 return tevent_req_post(req, ev);
1490 ok = SMBNTLMv2encrypt_hash(state,
1495 NULL, /* server_timestamp */
1497 &state->apassword_blob,
1498 &state->upassword_blob,
1499 &state->lm_session_key,
1500 &state->session_key);
1502 tevent_req_nterror(req,
1503 NT_STATUS_ACCESS_DENIED);
1504 return tevent_req_post(req, ev);
1507 state->upassword_blob = data_blob_talloc_zero(state, 24);
1508 if (tevent_req_nomem(state->upassword_blob.data, req)) {
1509 return tevent_req_post(req, ev);
1511 state->session_key = data_blob_talloc_zero(state, 16);
1512 if (tevent_req_nomem(state->session_key.data, req)) {
1513 return tevent_req_post(req, ev);
1516 SMBNTencrypt_hash(state->nt_hash, challenge.data,
1517 state->upassword_blob.data);
1518 SMBsesskeygen_ntv1(state->nt_hash,
1519 state->session_key.data);
1521 if (lp_client_lanman_auth()) {
1522 do_lmresponse = E_deshash(password,
1527 if (!lp_client_lanman_auth()) {
1528 DEBUG(1, ("Server requested LM password but "
1529 "'client lanman auth = no' "
1530 "or 'client ntlmv2 auth = yes' is set\n"));
1531 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1532 return tevent_req_post(req, ev);
1535 do_lmresponse = E_deshash(password, state->lm_hash);
1538 if (do_lmresponse) {
1539 state->apassword_blob = data_blob_talloc_zero(state, 24);
1540 if (tevent_req_nomem(state->apassword_blob.data, req)) {
1541 return tevent_req_post(req, ev);
1544 SMBencrypt_hash(state->lm_hash,
1546 state->apassword_blob.data);
1549 if (state->apassword_blob.length == 0) {
1550 if (state->upassword_blob.length == 0) {
1551 DEBUG(1, ("Password is > 14 chars in length, and is "
1552 "therefore incompatible with Lanman "
1553 "authentication\n"));
1554 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1555 return tevent_req_post(req, ev);
1559 * LM disabled, place NT# in LM field
1562 state->apassword_blob = state->upassword_blob;
1565 non_spnego_creds_done:
1567 in_buf_size = CLI_BUFFER_SIZE;
1568 in_mpx_max = smbXcli_conn_max_requests(cli->conn);
1569 in_vc_num = cli_state_get_vc_num(cli);
1570 in_sess_key = smb1cli_conn_server_session_key(cli->conn);
1571 in_native_os = "Unix";
1572 in_native_lm = "Samba";
1574 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1575 uint32_t in_capabilities = 0;
1577 in_capabilities = cli_session_setup_capabilities(cli, 0);
1580 * For now we keep the same values as before,
1581 * we may remove these in a separate commit later.
1585 subreq = smb1cli_session_setup_nt1_send(state, ev,
1596 state->apassword_blob,
1597 state->upassword_blob,
1601 if (tevent_req_nomem(subreq, req)) {
1602 return tevent_req_post(req, ev);
1604 tevent_req_set_callback(subreq, cli_session_setup_done_nt1,
1610 * For now we keep the same values as before,
1611 * we may remove these in a separate commit later.
1616 subreq = smb1cli_session_setup_lm21_send(state, ev,
1627 state->apassword_blob,
1630 if (tevent_req_nomem(subreq, req)) {
1631 return tevent_req_post(req, ev);
1633 tevent_req_set_callback(subreq, cli_session_setup_done_lm21,
1638 static void cli_session_setup_done_spnego(struct tevent_req *subreq)
1640 struct tevent_req *req = tevent_req_callback_data(
1641 subreq, struct tevent_req);
1644 status = cli_session_setup_spnego_recv(subreq);
1645 TALLOC_FREE(subreq);
1646 if (!ADS_ERR_OK(status)) {
1647 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1648 tevent_req_nterror(req, ads_ntstatus(status));
1651 tevent_req_done(req);
1654 static void cli_session_setup_done_nt1(struct tevent_req *subreq)
1656 struct tevent_req *req = tevent_req_callback_data(
1657 subreq, struct tevent_req);
1658 struct cli_session_setup_state *state = tevent_req_data(
1659 req, struct cli_session_setup_state);
1660 struct cli_state *cli = state->cli;
1662 struct iovec *recv_iov = NULL;
1663 const uint8_t *inbuf = NULL;
1666 status = smb1cli_session_setup_nt1_recv(subreq, state,
1669 &state->out_native_os,
1670 &state->out_native_lm,
1671 &state->out_primary_domain);
1672 TALLOC_FREE(subreq);
1673 if (!NT_STATUS_IS_OK(status)) {
1674 DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
1675 tevent_req_nterror(req, status);
1679 if (cli->server_os == NULL) {
1680 cli->server_os = talloc_move(cli, &state->out_native_os);
1682 if (cli->server_type == NULL) {
1683 cli->server_type = talloc_move(cli, &state->out_native_lm);
1685 if (cli->server_domain == NULL) {
1686 cli->server_domain = talloc_move(cli, &state->out_primary_domain);
1689 ok = smb1cli_conn_activate_signing(cli->conn,
1691 state->upassword_blob);
1693 ok = smb1cli_conn_check_signing(cli->conn, inbuf, 1);
1695 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1700 if (state->session_key.data) {
1701 struct smbXcli_session *session = cli->smb1.session;
1703 status = smb1cli_session_set_session_key(session,
1704 state->session_key);
1705 if (tevent_req_nterror(req, status)) {
1710 tevent_req_done(req);
1713 static void cli_session_setup_done_lm21(struct tevent_req *subreq)
1715 struct tevent_req *req = tevent_req_callback_data(
1716 subreq, struct tevent_req);
1717 struct cli_session_setup_state *state = tevent_req_data(
1718 req, struct cli_session_setup_state);
1719 struct cli_state *cli = state->cli;
1722 status = smb1cli_session_setup_lm21_recv(subreq, state,
1723 &state->out_native_os,
1724 &state->out_native_lm);
1725 TALLOC_FREE(subreq);
1726 if (!NT_STATUS_IS_OK(status)) {
1727 DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
1728 tevent_req_nterror(req, status);
1732 if (cli->server_os == NULL) {
1733 cli->server_os = talloc_move(cli, &state->out_native_os);
1735 if (cli->server_type == NULL) {
1736 cli->server_type = talloc_move(cli, &state->out_native_lm);
1739 tevent_req_done(req);
1742 NTSTATUS cli_session_setup_recv(struct tevent_req *req)
1744 return tevent_req_simple_recv_ntstatus(req);
1747 NTSTATUS cli_session_setup(struct cli_state *cli,
1750 const char *workgroup)
1752 struct tevent_context *ev;
1753 struct tevent_req *req;
1754 NTSTATUS status = NT_STATUS_NO_MEMORY;
1756 if (smbXcli_conn_has_async_calls(cli->conn)) {
1757 return NT_STATUS_INVALID_PARAMETER;
1759 ev = samba_tevent_context_init(talloc_tos());
1763 req = cli_session_setup_send(ev, ev, cli, user, pass, workgroup);
1767 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1770 status = cli_session_setup_recv(req);
1776 /****************************************************************************
1778 *****************************************************************************/
1780 struct cli_ulogoff_state {
1781 struct cli_state *cli;
1785 static void cli_ulogoff_done(struct tevent_req *subreq);
1787 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1788 struct tevent_context *ev,
1789 struct cli_state *cli)
1791 struct tevent_req *req, *subreq;
1792 struct cli_ulogoff_state *state;
1794 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1800 SCVAL(state->vwv+0, 0, 0xFF);
1801 SCVAL(state->vwv+1, 0, 0);
1802 SSVAL(state->vwv+2, 0, 0);
1804 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
1806 if (tevent_req_nomem(subreq, req)) {
1807 return tevent_req_post(req, ev);
1809 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1813 static void cli_ulogoff_done(struct tevent_req *subreq)
1815 struct tevent_req *req = tevent_req_callback_data(
1816 subreq, struct tevent_req);
1817 struct cli_ulogoff_state *state = tevent_req_data(
1818 req, struct cli_ulogoff_state);
1821 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1822 if (!NT_STATUS_IS_OK(status)) {
1823 tevent_req_nterror(req, status);
1826 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1827 tevent_req_done(req);
1830 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1832 return tevent_req_simple_recv_ntstatus(req);
1835 NTSTATUS cli_ulogoff(struct cli_state *cli)
1837 struct tevent_context *ev;
1838 struct tevent_req *req;
1839 NTSTATUS status = NT_STATUS_NO_MEMORY;
1841 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1842 status = smb2cli_logoff(cli->conn,
1845 if (!NT_STATUS_IS_OK(status)) {
1848 smb2cli_session_set_id_and_flags(cli->smb2.session,
1850 return NT_STATUS_OK;
1853 if (smbXcli_conn_has_async_calls(cli->conn)) {
1854 return NT_STATUS_INVALID_PARAMETER;
1856 ev = samba_tevent_context_init(talloc_tos());
1860 req = cli_ulogoff_send(ev, ev, cli);
1864 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1867 status = cli_ulogoff_recv(req);
1873 /****************************************************************************
1875 ****************************************************************************/
1877 struct cli_tcon_andx_state {
1878 struct cli_state *cli;
1883 static void cli_tcon_andx_done(struct tevent_req *subreq);
1885 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1886 struct tevent_context *ev,
1887 struct cli_state *cli,
1888 const char *share, const char *dev,
1889 const char *pass, int passlen,
1890 struct tevent_req **psmbreq)
1892 struct tevent_req *req, *subreq;
1893 struct cli_tcon_andx_state *state;
1898 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1899 uint16_t tcon_flags = 0;
1903 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1910 cli->share = talloc_strdup(cli, share);
1915 /* in user level security don't send a password now */
1916 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1919 } else if (pass == NULL) {
1920 DEBUG(1, ("Server not using user level security and no "
1921 "password supplied.\n"));
1925 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1926 *pass && passlen != 24) {
1927 if (!lp_client_lanman_auth()) {
1928 DEBUG(1, ("Server requested LANMAN password "
1929 "(share-level security) but "
1930 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
1935 * Non-encrypted passwords - convert to DOS codepage before
1938 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
1940 pass = (const char *)p24;
1942 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1943 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1947 if (!lp_client_plaintext_auth() && (*pass)) {
1948 DEBUG(1, ("Server requested PLAINTEXT "
1950 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
1955 * Non-encrypted passwords - convert to DOS codepage
1958 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
1959 if (tevent_req_nomem(tmp_pass, req)) {
1960 return tevent_req_post(req, ev);
1962 tmp_pass = trans2_bytes_push_str(tmp_pass,
1963 false, /* always DOS */
1967 if (tevent_req_nomem(tmp_pass, req)) {
1968 return tevent_req_post(req, ev);
1970 pass = (const char *)tmp_pass;
1971 passlen = talloc_get_size(tmp_pass);
1975 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
1976 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
1978 SCVAL(vwv+0, 0, 0xFF);
1981 SSVAL(vwv+2, 0, tcon_flags);
1982 SSVAL(vwv+3, 0, passlen);
1984 if (passlen && pass) {
1985 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
1987 bytes = talloc_array(state, uint8_t, 0);
1993 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1994 smbXcli_conn_remote_name(cli->conn), share);
1999 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2004 * Add the devicetype
2006 tmp = talloc_strdup_upper(talloc_tos(), dev);
2011 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2014 if (bytes == NULL) {
2019 state->bytes.iov_base = (void *)bytes;
2020 state->bytes.iov_len = talloc_get_size(bytes);
2022 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
2024 if (subreq == NULL) {
2028 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2033 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2034 return tevent_req_post(req, ev);
2037 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2038 struct tevent_context *ev,
2039 struct cli_state *cli,
2040 const char *share, const char *dev,
2041 const char *pass, int passlen)
2043 struct tevent_req *req, *subreq;
2046 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2051 if (subreq == NULL) {
2054 status = smb1cli_req_chain_submit(&subreq, 1);
2055 if (!NT_STATUS_IS_OK(status)) {
2056 tevent_req_nterror(req, status);
2057 return tevent_req_post(req, ev);
2062 static void cli_tcon_andx_done(struct tevent_req *subreq)
2064 struct tevent_req *req = tevent_req_callback_data(
2065 subreq, struct tevent_req);
2066 struct cli_tcon_andx_state *state = tevent_req_data(
2067 req, struct cli_tcon_andx_state);
2068 struct cli_state *cli = state->cli;
2076 uint16_t optional_support = 0;
2078 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2079 &num_bytes, &bytes);
2080 TALLOC_FREE(subreq);
2081 if (!NT_STATUS_IS_OK(status)) {
2082 tevent_req_nterror(req, status);
2086 inhdr = in + NBT_HDR_SIZE;
2089 if (clistr_pull_talloc(cli,
2090 (const char *)inhdr,
2091 SVAL(inhdr, HDR_FLG2),
2095 STR_TERMINATE|STR_ASCII) == -1) {
2096 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2100 cli->dev = talloc_strdup(cli, "");
2101 if (cli->dev == NULL) {
2102 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2107 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2108 /* almost certainly win95 - enable bug fixes */
2113 * Make sure that we have the optional support 16-bit field. WCT > 2.
2114 * Avoids issues when connecting to Win9x boxes sharing files
2117 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2118 optional_support = SVAL(vwv+2, 0);
2121 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2122 smb1cli_session_protect_session_key(cli->smb1.session);
2125 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2126 SVAL(inhdr, HDR_TID),
2128 0, /* maximal_access */
2129 0, /* guest_maximal_access */
2131 NULL); /* fs_type */
2133 tevent_req_done(req);
2136 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2138 return tevent_req_simple_recv_ntstatus(req);
2141 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2142 const char *dev, const char *pass, int passlen)
2144 TALLOC_CTX *frame = talloc_stackframe();
2145 struct tevent_context *ev;
2146 struct tevent_req *req;
2147 NTSTATUS status = NT_STATUS_NO_MEMORY;
2149 if (smbXcli_conn_has_async_calls(cli->conn)) {
2151 * Can't use sync call while an async call is in flight
2153 status = NT_STATUS_INVALID_PARAMETER;
2157 ev = samba_tevent_context_init(frame);
2162 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2167 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2171 status = cli_tcon_andx_recv(req);
2177 struct cli_tree_connect_state {
2178 struct cli_state *cli;
2181 static struct tevent_req *cli_raw_tcon_send(
2182 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2183 const char *service, const char *pass, const char *dev);
2184 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2185 uint16_t *max_xmit, uint16_t *tid);
2187 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2188 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2189 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2191 static struct tevent_req *cli_tree_connect_send(
2192 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2193 const char *share, const char *dev, const char *pass, int passlen)
2195 struct tevent_req *req, *subreq;
2196 struct cli_tree_connect_state *state;
2198 req = tevent_req_create(mem_ctx, &state,
2199 struct cli_tree_connect_state);
2205 cli->share = talloc_strdup(cli, share);
2206 if (tevent_req_nomem(cli->share, req)) {
2207 return tevent_req_post(req, ev);
2210 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2213 cli->smb2.tcon = smbXcli_tcon_create(cli);
2214 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2215 return tevent_req_post(req, ev);
2218 unc = talloc_asprintf(state, "\\\\%s\\%s",
2219 smbXcli_conn_remote_name(cli->conn),
2221 if (tevent_req_nomem(unc, req)) {
2222 return tevent_req_post(req, ev);
2225 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2226 cli->smb2.session, cli->smb2.tcon,
2229 if (tevent_req_nomem(subreq, req)) {
2230 return tevent_req_post(req, ev);
2232 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2237 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2238 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2240 if (tevent_req_nomem(subreq, req)) {
2241 return tevent_req_post(req, ev);
2243 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2248 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2249 if (tevent_req_nomem(subreq, req)) {
2250 return tevent_req_post(req, ev);
2252 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2257 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2259 tevent_req_simple_finish_ntstatus(
2260 subreq, smb2cli_tcon_recv(subreq));
2263 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2265 tevent_req_simple_finish_ntstatus(
2266 subreq, cli_tcon_andx_recv(subreq));
2269 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2271 struct tevent_req *req = tevent_req_callback_data(
2272 subreq, struct tevent_req);
2273 struct cli_tree_connect_state *state = tevent_req_data(
2274 req, struct cli_tree_connect_state);
2276 uint16_t max_xmit = 0;
2279 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2280 if (tevent_req_nterror(req, status)) {
2284 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2286 0, /* optional_support */
2287 0, /* maximal_access */
2288 0, /* guest_maximal_access */
2290 NULL); /* fs_type */
2292 tevent_req_done(req);
2295 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2297 return tevent_req_simple_recv_ntstatus(req);
2300 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2301 const char *dev, const char *pass, int passlen)
2303 struct tevent_context *ev;
2304 struct tevent_req *req;
2305 NTSTATUS status = NT_STATUS_NO_MEMORY;
2307 if (smbXcli_conn_has_async_calls(cli->conn)) {
2308 return NT_STATUS_INVALID_PARAMETER;
2310 ev = samba_tevent_context_init(talloc_tos());
2314 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2318 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2321 status = cli_tree_connect_recv(req);
2327 /****************************************************************************
2328 Send a tree disconnect.
2329 ****************************************************************************/
2331 struct cli_tdis_state {
2332 struct cli_state *cli;
2335 static void cli_tdis_done(struct tevent_req *subreq);
2337 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2338 struct tevent_context *ev,
2339 struct cli_state *cli)
2341 struct tevent_req *req, *subreq;
2342 struct cli_tdis_state *state;
2344 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2350 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2351 if (tevent_req_nomem(subreq, req)) {
2352 return tevent_req_post(req, ev);
2354 tevent_req_set_callback(subreq, cli_tdis_done, req);
2358 static void cli_tdis_done(struct tevent_req *subreq)
2360 struct tevent_req *req = tevent_req_callback_data(
2361 subreq, struct tevent_req);
2362 struct cli_tdis_state *state = tevent_req_data(
2363 req, struct cli_tdis_state);
2366 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2367 TALLOC_FREE(subreq);
2368 if (!NT_STATUS_IS_OK(status)) {
2369 tevent_req_nterror(req, status);
2372 cli_state_set_tid(state->cli, UINT16_MAX);
2373 tevent_req_done(req);
2376 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2378 return tevent_req_simple_recv_ntstatus(req);
2381 NTSTATUS cli_tdis(struct cli_state *cli)
2383 struct tevent_context *ev;
2384 struct tevent_req *req;
2385 NTSTATUS status = NT_STATUS_NO_MEMORY;
2387 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2388 return smb2cli_tdis(cli->conn,
2394 if (smbXcli_conn_has_async_calls(cli->conn)) {
2395 return NT_STATUS_INVALID_PARAMETER;
2397 ev = samba_tevent_context_init(talloc_tos());
2401 req = cli_tdis_send(ev, ev, cli);
2405 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2408 status = cli_tdis_recv(req);
2414 struct cli_connect_sock_state {
2415 const char **called_names;
2416 const char **calling_names;
2422 static void cli_connect_sock_done(struct tevent_req *subreq);
2425 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2429 static struct tevent_req *cli_connect_sock_send(
2430 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2431 const char *host, int name_type, const struct sockaddr_storage *pss,
2432 const char *myname, uint16_t port)
2434 struct tevent_req *req, *subreq;
2435 struct cli_connect_sock_state *state;
2437 struct sockaddr_storage *addrs;
2438 unsigned i, num_addrs;
2441 req = tevent_req_create(mem_ctx, &state,
2442 struct cli_connect_sock_state);
2447 prog = getenv("LIBSMB_PROG");
2449 state->fd = sock_exec(prog);
2450 if (state->fd == -1) {
2451 status = map_nt_error_from_unix(errno);
2452 tevent_req_nterror(req, status);
2455 tevent_req_done(req);
2457 return tevent_req_post(req, ev);
2460 if ((pss == NULL) || is_zero_addr(pss)) {
2463 * Here we cheat. resolve_name_list is not async at all. So
2464 * this call will only be really async if the name lookup has
2465 * been done externally.
2468 status = resolve_name_list(state, host, name_type,
2469 &addrs, &num_addrs);
2470 if (!NT_STATUS_IS_OK(status)) {
2471 tevent_req_nterror(req, status);
2472 return tevent_req_post(req, ev);
2475 addrs = talloc_array(state, struct sockaddr_storage, 1);
2476 if (tevent_req_nomem(addrs, req)) {
2477 return tevent_req_post(req, ev);
2483 state->called_names = talloc_array(state, const char *, num_addrs);
2484 if (tevent_req_nomem(state->called_names, req)) {
2485 return tevent_req_post(req, ev);
2487 state->called_types = talloc_array(state, int, num_addrs);
2488 if (tevent_req_nomem(state->called_types, req)) {
2489 return tevent_req_post(req, ev);
2491 state->calling_names = talloc_array(state, const char *, num_addrs);
2492 if (tevent_req_nomem(state->calling_names, req)) {
2493 return tevent_req_post(req, ev);
2495 for (i=0; i<num_addrs; i++) {
2496 state->called_names[i] = host;
2497 state->called_types[i] = name_type;
2498 state->calling_names[i] = myname;
2501 subreq = smbsock_any_connect_send(
2502 state, ev, addrs, state->called_names, state->called_types,
2503 state->calling_names, NULL, num_addrs, port);
2504 if (tevent_req_nomem(subreq, req)) {
2505 return tevent_req_post(req, ev);
2507 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2511 static void cli_connect_sock_done(struct tevent_req *subreq)
2513 struct tevent_req *req = tevent_req_callback_data(
2514 subreq, struct tevent_req);
2515 struct cli_connect_sock_state *state = tevent_req_data(
2516 req, struct cli_connect_sock_state);
2519 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2521 TALLOC_FREE(subreq);
2522 if (tevent_req_nterror(req, status)) {
2525 set_socket_options(state->fd, lp_socket_options());
2526 tevent_req_done(req);
2529 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2530 int *pfd, uint16_t *pport)
2532 struct cli_connect_sock_state *state = tevent_req_data(
2533 req, struct cli_connect_sock_state);
2536 if (tevent_req_is_nterror(req, &status)) {
2540 *pport = state->port;
2541 return NT_STATUS_OK;
2544 struct cli_connect_nb_state {
2545 const char *desthost;
2548 struct cli_state *cli;
2551 static void cli_connect_nb_done(struct tevent_req *subreq);
2553 static struct tevent_req *cli_connect_nb_send(
2554 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2555 const char *host, const struct sockaddr_storage *dest_ss,
2556 uint16_t port, int name_type, const char *myname,
2557 int signing_state, int flags)
2559 struct tevent_req *req, *subreq;
2560 struct cli_connect_nb_state *state;
2562 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2566 state->signing_state = signing_state;
2567 state->flags = flags;
2570 char *p = strchr(host, '#');
2573 name_type = strtol(p+1, NULL, 16);
2574 host = talloc_strndup(state, host, p - host);
2575 if (tevent_req_nomem(host, req)) {
2576 return tevent_req_post(req, ev);
2580 state->desthost = host;
2581 } else if (dest_ss != NULL) {
2582 state->desthost = print_canonical_sockaddr(state, dest_ss);
2583 if (tevent_req_nomem(state->desthost, req)) {
2584 return tevent_req_post(req, ev);
2587 /* No host or dest_ss given. Error out. */
2588 tevent_req_error(req, EINVAL);
2589 return tevent_req_post(req, ev);
2592 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2594 if (tevent_req_nomem(subreq, req)) {
2595 return tevent_req_post(req, ev);
2597 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2601 static void cli_connect_nb_done(struct tevent_req *subreq)
2603 struct tevent_req *req = tevent_req_callback_data(
2604 subreq, struct tevent_req);
2605 struct cli_connect_nb_state *state = tevent_req_data(
2606 req, struct cli_connect_nb_state);
2611 status = cli_connect_sock_recv(subreq, &fd, &port);
2612 TALLOC_FREE(subreq);
2613 if (tevent_req_nterror(req, status)) {
2617 state->cli = cli_state_create(state, fd, state->desthost, NULL,
2618 state->signing_state, state->flags);
2619 if (tevent_req_nomem(state->cli, req)) {
2623 tevent_req_done(req);
2626 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
2627 struct cli_state **pcli)
2629 struct cli_connect_nb_state *state = tevent_req_data(
2630 req, struct cli_connect_nb_state);
2633 if (tevent_req_is_nterror(req, &status)) {
2636 *pcli = talloc_move(NULL, &state->cli);
2637 return NT_STATUS_OK;
2640 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2641 uint16_t port, int name_type, const char *myname,
2642 int signing_state, int flags, struct cli_state **pcli)
2644 struct tevent_context *ev;
2645 struct tevent_req *req;
2646 NTSTATUS status = NT_STATUS_NO_MEMORY;
2648 ev = samba_tevent_context_init(talloc_tos());
2652 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
2653 myname, signing_state, flags);
2657 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
2660 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2663 status = cli_connect_nb_recv(req, pcli);
2669 struct cli_start_connection_state {
2670 struct tevent_context *ev;
2671 struct cli_state *cli;
2676 static void cli_start_connection_connected(struct tevent_req *subreq);
2677 static void cli_start_connection_done(struct tevent_req *subreq);
2680 establishes a connection to after the negprot.
2681 @param output_cli A fully initialised cli structure, non-null only on success
2682 @param dest_host The netbios name of the remote host
2683 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2684 @param port (optional) The destination port (0 for default)
2687 static struct tevent_req *cli_start_connection_send(
2688 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2689 const char *my_name, const char *dest_host,
2690 const struct sockaddr_storage *dest_ss, int port,
2691 int signing_state, int flags)
2693 struct tevent_req *req, *subreq;
2694 struct cli_start_connection_state *state;
2696 req = tevent_req_create(mem_ctx, &state,
2697 struct cli_start_connection_state);
2703 if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
2704 state->min_protocol = lp_client_ipc_min_protocol();
2705 state->max_protocol = lp_client_ipc_max_protocol();
2707 state->min_protocol = lp_client_min_protocol();
2708 state->max_protocol = lp_client_max_protocol();
2711 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
2712 0x20, my_name, signing_state, flags);
2713 if (tevent_req_nomem(subreq, req)) {
2714 return tevent_req_post(req, ev);
2716 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
2720 static void cli_start_connection_connected(struct tevent_req *subreq)
2722 struct tevent_req *req = tevent_req_callback_data(
2723 subreq, struct tevent_req);
2724 struct cli_start_connection_state *state = tevent_req_data(
2725 req, struct cli_start_connection_state);
2728 status = cli_connect_nb_recv(subreq, &state->cli);
2729 TALLOC_FREE(subreq);
2730 if (tevent_req_nterror(req, status)) {
2734 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
2735 state->cli->timeout,
2736 state->min_protocol,
2737 state->max_protocol);
2738 if (tevent_req_nomem(subreq, req)) {
2741 tevent_req_set_callback(subreq, cli_start_connection_done, req);
2744 static void cli_start_connection_done(struct tevent_req *subreq)
2746 struct tevent_req *req = tevent_req_callback_data(
2747 subreq, struct tevent_req);
2748 struct cli_start_connection_state *state = tevent_req_data(
2749 req, struct cli_start_connection_state);
2752 status = smbXcli_negprot_recv(subreq);
2753 TALLOC_FREE(subreq);
2754 if (tevent_req_nterror(req, status)) {
2758 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
2759 /* Ensure we ask for some initial credits. */
2760 smb2cli_conn_set_max_credits(state->cli->conn,
2761 DEFAULT_SMB2_MAX_CREDITS);
2764 tevent_req_done(req);
2767 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
2768 struct cli_state **output_cli)
2770 struct cli_start_connection_state *state = tevent_req_data(
2771 req, struct cli_start_connection_state);
2774 if (tevent_req_is_nterror(req, &status)) {
2777 *output_cli = state->cli;
2779 return NT_STATUS_OK;
2782 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2783 const char *my_name,
2784 const char *dest_host,
2785 const struct sockaddr_storage *dest_ss, int port,
2786 int signing_state, int flags)
2788 struct tevent_context *ev;
2789 struct tevent_req *req;
2790 NTSTATUS status = NT_STATUS_NO_MEMORY;
2792 ev = samba_tevent_context_init(talloc_tos());
2796 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
2797 port, signing_state, flags);
2801 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2804 status = cli_start_connection_recv(req, output_cli);
2811 establishes a connection right up to doing tconX, password specified.
2812 @param output_cli A fully initialised cli structure, non-null only on success
2813 @param dest_host The netbios name of the remote host
2814 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2815 @param port (optional) The destination port (0 for default)
2816 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2817 @param service_type The 'type' of serivice.
2818 @param user Username, unix string
2819 @param domain User's domain
2820 @param password User's password, unencrypted unix string.
2823 struct cli_full_connection_state {
2824 struct tevent_context *ev;
2825 const char *service;
2826 const char *service_type;
2829 const char *password;
2832 struct cli_state *cli;
2835 static int cli_full_connection_state_destructor(
2836 struct cli_full_connection_state *s);
2837 static void cli_full_connection_started(struct tevent_req *subreq);
2838 static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
2839 static void cli_full_connection_done(struct tevent_req *subreq);
2841 struct tevent_req *cli_full_connection_send(
2842 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2843 const char *my_name, const char *dest_host,
2844 const struct sockaddr_storage *dest_ss, int port,
2845 const char *service, const char *service_type,
2846 const char *user, const char *domain,
2847 const char *password, int flags, int signing_state)
2849 struct tevent_req *req, *subreq;
2850 struct cli_full_connection_state *state;
2852 req = tevent_req_create(mem_ctx, &state,
2853 struct cli_full_connection_state);
2857 talloc_set_destructor(state, cli_full_connection_state_destructor);
2860 state->service = service;
2861 state->service_type = service_type;
2863 state->domain = domain;
2864 state->password = password;
2865 state->flags = flags;
2867 state->pw_len = state->password ? strlen(state->password)+1 : 0;
2868 if (state->password == NULL) {
2869 state->password = "";
2872 subreq = cli_start_connection_send(
2873 state, ev, my_name, dest_host, dest_ss, port,
2874 signing_state, flags);
2875 if (tevent_req_nomem(subreq, req)) {
2876 return tevent_req_post(req, ev);
2878 tevent_req_set_callback(subreq, cli_full_connection_started, req);
2882 static int cli_full_connection_state_destructor(
2883 struct cli_full_connection_state *s)
2885 if (s->cli != NULL) {
2886 cli_shutdown(s->cli);
2892 static void cli_full_connection_started(struct tevent_req *subreq)
2894 struct tevent_req *req = tevent_req_callback_data(
2895 subreq, struct tevent_req);
2896 struct cli_full_connection_state *state = tevent_req_data(
2897 req, struct cli_full_connection_state);
2900 status = cli_start_connection_recv(subreq, &state->cli);
2901 TALLOC_FREE(subreq);
2902 if (tevent_req_nterror(req, status)) {
2905 subreq = cli_session_setup_send(
2906 state, state->ev, state->cli, state->user,
2907 state->password, state->domain);
2908 if (tevent_req_nomem(subreq, req)) {
2911 tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
2914 static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
2916 struct tevent_req *req = tevent_req_callback_data(
2917 subreq, struct tevent_req);
2918 struct cli_full_connection_state *state = tevent_req_data(
2919 req, struct cli_full_connection_state);
2922 status = cli_session_setup_recv(subreq);
2923 TALLOC_FREE(subreq);
2925 if (!NT_STATUS_IS_OK(status) &&
2926 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2928 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2930 subreq = cli_session_setup_send(
2931 state, state->ev, state->cli, "", "",
2933 if (tevent_req_nomem(subreq, req)) {
2936 tevent_req_set_callback(
2937 subreq, cli_full_connection_sess_set_up, req);
2941 if (tevent_req_nterror(req, status)) {
2945 if (state->service != NULL) {
2946 subreq = cli_tree_connect_send(
2947 state, state->ev, state->cli,
2948 state->service, state->service_type,
2949 state->password, state->pw_len);
2950 if (tevent_req_nomem(subreq, req)) {
2953 tevent_req_set_callback(subreq, cli_full_connection_done, req);
2957 tevent_req_done(req);
2960 static void cli_full_connection_done(struct tevent_req *subreq)
2962 struct tevent_req *req = tevent_req_callback_data(
2963 subreq, struct tevent_req);
2966 status = cli_tree_connect_recv(subreq);
2967 TALLOC_FREE(subreq);
2968 if (tevent_req_nterror(req, status)) {
2972 tevent_req_done(req);
2975 NTSTATUS cli_full_connection_recv(struct tevent_req *req,
2976 struct cli_state **output_cli)
2978 struct cli_full_connection_state *state = tevent_req_data(
2979 req, struct cli_full_connection_state);
2982 if (tevent_req_is_nterror(req, &status)) {
2985 *output_cli = state->cli;
2986 talloc_set_destructor(state, NULL);
2987 return NT_STATUS_OK;
2990 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2991 const char *my_name,
2992 const char *dest_host,
2993 const struct sockaddr_storage *dest_ss, int port,
2994 const char *service, const char *service_type,
2995 const char *user, const char *domain,
2996 const char *password, int flags,
2999 struct tevent_context *ev;
3000 struct tevent_req *req;
3001 NTSTATUS status = NT_STATUS_NO_MEMORY;
3003 ev = samba_tevent_context_init(talloc_tos());
3007 req = cli_full_connection_send(
3008 ev, ev, my_name, dest_host, dest_ss, port, service,
3009 service_type, user, domain, password, flags, signing_state);
3013 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3016 status = cli_full_connection_recv(req, output_cli);
3022 /****************************************************************************
3023 Send an old style tcon.
3024 ****************************************************************************/
3025 struct cli_raw_tcon_state {
3029 static void cli_raw_tcon_done(struct tevent_req *subreq);
3031 static struct tevent_req *cli_raw_tcon_send(
3032 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3033 const char *service, const char *pass, const char *dev)
3035 struct tevent_req *req, *subreq;
3036 struct cli_raw_tcon_state *state;
3039 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3044 if (!lp_client_plaintext_auth() && (*pass)) {
3045 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3046 " or 'client ntlmv2 auth = yes'\n"));
3047 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3048 return tevent_req_post(req, ev);
3051 bytes = talloc_array(state, uint8_t, 0);
3052 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3053 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3054 service, strlen(service)+1, NULL);
3055 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3056 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3057 pass, strlen(pass)+1, NULL);
3058 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3059 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3060 dev, strlen(dev)+1, NULL);
3062 if (tevent_req_nomem(bytes, req)) {
3063 return tevent_req_post(req, ev);
3066 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3067 talloc_get_size(bytes), bytes);
3068 if (tevent_req_nomem(subreq, req)) {
3069 return tevent_req_post(req, ev);
3071 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3075 static void cli_raw_tcon_done(struct tevent_req *subreq)
3077 struct tevent_req *req = tevent_req_callback_data(
3078 subreq, struct tevent_req);
3079 struct cli_raw_tcon_state *state = tevent_req_data(
3080 req, struct cli_raw_tcon_state);
3083 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3085 TALLOC_FREE(subreq);
3086 if (tevent_req_nterror(req, status)) {
3089 tevent_req_done(req);
3092 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3093 uint16_t *max_xmit, uint16_t *tid)
3095 struct cli_raw_tcon_state *state = tevent_req_data(
3096 req, struct cli_raw_tcon_state);
3099 if (tevent_req_is_nterror(req, &status)) {
3102 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3103 *tid = SVAL(state->ret_vwv + 1, 0);
3104 return NT_STATUS_OK;
3107 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3108 const char *service, const char *pass, const char *dev,
3109 uint16_t *max_xmit, uint16_t *tid)
3111 struct tevent_context *ev;
3112 struct tevent_req *req;
3113 NTSTATUS status = NT_STATUS_NO_MEMORY;
3115 ev = samba_tevent_context_init(talloc_tos());
3119 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3123 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3126 status = cli_raw_tcon_recv(req, max_xmit, tid);
3132 /* Return a cli_state pointing at the IPC$ share for the given server */
3134 struct cli_state *get_ipc_connect(char *server,
3135 struct sockaddr_storage *server_ss,
3136 const struct user_auth_info *user_info)
3138 struct cli_state *cli;
3140 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3142 if (get_cmdline_auth_info_use_kerberos(user_info)) {
3143 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3146 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3147 get_cmdline_auth_info_username(user_info),
3149 get_cmdline_auth_info_password(user_info),
3151 SMB_SIGNING_DEFAULT);
3153 if (NT_STATUS_IS_OK(nt_status)) {
3155 } else if (is_ipaddress(server)) {
3156 /* windows 9* needs a correct NMB name for connections */
3157 fstring remote_name;
3159 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3160 cli = get_ipc_connect(remote_name, server_ss, user_info);
3169 * Given the IP address of a master browser on the network, return its
3170 * workgroup and connect to it.
3172 * This function is provided to allow additional processing beyond what
3173 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3174 * browsers and obtain each master browsers' list of domains (in case the
3175 * first master browser is recently on the network and has not yet
3176 * synchronized with other master browsers and therefore does not yet have the
3177 * entire network browse list)
3180 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3181 struct sockaddr_storage *mb_ip,
3182 const struct user_auth_info *user_info,
3183 char **pp_workgroup_out)
3185 char addr[INET6_ADDRSTRLEN];
3187 struct cli_state *cli;
3188 struct sockaddr_storage server_ss;
3190 *pp_workgroup_out = NULL;
3192 print_sockaddr(addr, sizeof(addr), mb_ip);
3193 DEBUG(99, ("Looking up name of master browser %s\n",
3197 * Do a name status query to find out the name of the master browser.
3198 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3199 * master browser will not respond to a wildcard query (or, at least,
3200 * an NT4 server acting as the domain master browser will not).
3202 * We might be able to use ONLY the query on MSBROWSE, but that's not
3203 * yet been tested with all Windows versions, so until it is, leave
3204 * the original wildcard query as the first choice and fall back to
3205 * MSBROWSE if the wildcard query fails.
3207 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3208 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3210 DEBUG(99, ("Could not retrieve name status for %s\n",
3215 if (!find_master_ip(name, &server_ss)) {
3216 DEBUG(99, ("Could not find master ip for %s\n", name));
3220 *pp_workgroup_out = talloc_strdup(ctx, name);
3222 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3224 print_sockaddr(addr, sizeof(addr), &server_ss);
3225 cli = get_ipc_connect(addr, &server_ss, user_info);
3231 * Return the IP address and workgroup of a master browser on the network, and
3235 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3236 const struct user_auth_info *user_info,
3237 char **pp_workgroup_out)
3239 struct sockaddr_storage *ip_list;
3240 struct cli_state *cli;
3244 *pp_workgroup_out = NULL;
3246 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3248 /* Go looking for workgroups by broadcasting on the local network */
3250 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3252 if (!NT_STATUS_IS_OK(status)) {
3253 DEBUG(99, ("No master browsers responded: %s\n",
3254 nt_errstr(status)));
3258 for (i = 0; i < count; i++) {
3259 char addr[INET6_ADDRSTRLEN];
3260 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3261 DEBUG(99, ("Found master browser %s\n", addr));
3263 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3264 user_info, pp_workgroup_out);