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 "../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 cli_credentials_set_conf(creds, lp_ctx);
77 if (username == NULL) {
81 if (strlen(username) == 0) {
82 if (password != NULL && strlen(password) == 0) {
84 * some callers pass "" as no password
86 * gensec only handles NULL as no password.
90 if (password == NULL) {
91 cli_credentials_set_anonymous(creds);
96 tmp = talloc_strdup(creds, username);
102 /* allow for workgroups as part of the username */
103 if ((p = strchr_m(tmp, '\\')) ||
104 (p = strchr_m(tmp, '/')) ||
105 (p = strchr_m(tmp, *lp_winbind_separator()))) {
111 principal = username;
112 username = cli_session_setup_get_account(creds, principal);
113 if (username == NULL) {
116 ok = strequal(username, principal);
119 * Ok still the same, so it's not a principal
124 if (use_kerberos && fallback_after_kerberos) {
125 cli_credentials_set_kerberos_state(creds,
126 CRED_AUTO_USE_KERBEROS);
127 } else if (use_kerberos) {
128 cli_credentials_set_kerberos_state(creds,
129 CRED_MUST_USE_KERBEROS);
131 cli_credentials_set_kerberos_state(creds,
132 CRED_DONT_USE_KERBEROS);
138 features = cli_credentials_get_gensec_features(creds);
139 features |= GENSEC_FEATURE_NTLM_CCACHE;
140 cli_credentials_set_gensec_features(creds, features);
142 if (password != NULL && strlen(password) == 0) {
144 * some callers pass "" as no password
146 * GENSEC_FEATURE_NTLM_CCACHE only handles
147 * NULL as no password.
153 ok = cli_credentials_set_username(creds,
160 if (domain != NULL) {
161 ok = cli_credentials_set_domain(creds,
169 if (principal != NULL) {
170 ok = cli_credentials_set_principal(creds,
179 ok = cli_credentials_set_realm(creds,
187 if (password != NULL && strlen(password) > 0) {
188 if (password_is_nt_hash) {
189 struct samr_Password nt_hash;
192 converted = strhex_to_str((char *)nt_hash.hash,
193 sizeof(nt_hash.hash),
196 if (converted != sizeof(nt_hash.hash)) {
200 ok = cli_credentials_set_nt_hash(creds,
207 ok = cli_credentials_set_password(creds,
222 NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli,
223 struct cli_credentials *creds)
225 TALLOC_CTX *frame = talloc_stackframe();
226 const char *user_principal = NULL;
227 const char *user_account = NULL;
228 const char *user_domain = NULL;
229 const char *pass = NULL;
230 const char *target_hostname = NULL;
231 const DATA_BLOB *server_blob = NULL;
232 bool got_kerberos_mechanism = false;
233 enum credentials_use_kerberos krb5_state;
234 bool try_kerberos = false;
235 bool need_kinit = false;
236 bool auth_requested = true;
239 target_hostname = smbXcli_conn_remote_name(cli->conn);
240 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
242 /* the server might not even do spnego */
243 if (server_blob != NULL && server_blob->length != 0) {
244 char *OIDs[ASN1_MAX_OIDS] = { NULL, };
249 * The server sent us the first part of the SPNEGO exchange in the
250 * negprot reply. It is WRONG to depend on the principal sent in the
251 * negprot reply, but right now we do it. If we don't receive one,
252 * we try to best guess, then fall back to NTLM.
254 ok = spnego_parse_negTokenInit(frame,
261 return NT_STATUS_INVALID_PARAMETER;
263 if (OIDs[0] == NULL) {
265 return NT_STATUS_INVALID_PARAMETER;
268 /* make sure the server understands kerberos */
269 for (i = 0; OIDs[i] != NULL; i++) {
271 DEBUG(3,("got OID=%s\n", OIDs[i]));
273 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
276 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
277 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
278 got_kerberos_mechanism = true;
284 auth_requested = cli_credentials_authentication_requested(creds);
285 if (auth_requested) {
286 user_principal = cli_credentials_get_principal(creds, frame);
287 if (user_principal == NULL) {
289 return NT_STATUS_NO_MEMORY;
292 user_account = cli_credentials_get_username(creds);
293 user_domain = cli_credentials_get_domain(creds);
294 pass = cli_credentials_get_password(creds);
296 krb5_state = cli_credentials_get_kerberos_state(creds);
298 if (krb5_state != CRED_DONT_USE_KERBEROS) {
302 if (target_hostname == NULL) {
303 try_kerberos = false;
304 } else if (is_ipaddress(target_hostname)) {
305 try_kerberos = false;
306 } else if (strequal(target_hostname, "localhost")) {
307 try_kerberos = false;
308 } else if (strequal(target_hostname, STAR_SMBSERVER)) {
309 try_kerberos = false;
310 } else if (!auth_requested) {
311 try_kerberos = false;
314 if (krb5_state == CRED_MUST_USE_KERBEROS && !try_kerberos) {
315 DEBUG(0, ("Kerberos auth with '%s' (%s\\%s) to access "
316 "'%s' not possible\n",
317 user_principal, user_domain, user_account,
320 return NT_STATUS_ACCESS_DENIED;
323 if (pass == NULL || strlen(pass) == 0) {
325 } else if (krb5_state == CRED_MUST_USE_KERBEROS) {
326 need_kinit = try_kerberos;
327 } else if (!got_kerberos_mechanism) {
329 * Most likely the server doesn't support
330 * Kerberos, don't waste time doing a kinit
334 need_kinit = try_kerberos;
344 * TODO: This should be done within the gensec layer
347 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
348 ret = kerberos_kinit_password(user_principal, pass,
349 0 /* no time correction for now */,
352 int dbglvl = DBGLVL_WARNING;
354 if (krb5_state == CRED_MUST_USE_KERBEROS) {
358 DEBUG(dbglvl, ("Kinit for %s to access %s failed: %s\n",
359 user_principal, target_hostname,
360 error_message(ret)));
361 if (krb5_state == CRED_MUST_USE_KERBEROS) {
363 return krb5_to_nt_status(ret);
367 * Ignore the error and hope that NTLM will work
375 /********************************************************
376 Utility function to ensure we always return at least
377 a valid char * pointer to an empty string for the
378 cli->server_os, cli->server_type and cli->server_domain
380 *******************************************************/
382 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
389 *destlen = clistr_pull_talloc(mem_ctx,
396 if (*destlen == -1) {
397 return NT_STATUS_NO_MEMORY;
401 *dest = talloc_strdup(mem_ctx, "");
403 return NT_STATUS_NO_MEMORY;
409 /****************************************************************************
410 Work out suitable capabilities to offer the server.
411 ****************************************************************************/
413 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
414 uint32_t sesssetup_capabilities)
416 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
419 * We only send capabilities based on the mask for:
420 * - client only flags
421 * - flags used in both directions
423 * We do not echo the server only flags, except some legacy flags.
425 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
426 * CAP_LARGE_WRITEX in order to allow us to do large reads
427 * against old Samba releases (<= 3.6.x).
429 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
432 * Session Setup specific flags CAP_DYNAMIC_REAUTH
433 * and CAP_EXTENDED_SECURITY are passed by the caller.
434 * We need that in order to do guest logins even if
435 * CAP_EXTENDED_SECURITY is negotiated.
437 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
438 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
439 client_capabilities |= sesssetup_capabilities;
441 return client_capabilities;
444 /****************************************************************************
445 Do a NT1 guest session setup.
446 ****************************************************************************/
448 struct cli_session_setup_guest_state {
449 struct cli_state *cli;
454 static void cli_session_setup_guest_done(struct tevent_req *subreq);
456 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
457 struct tevent_context *ev,
458 struct cli_state *cli,
459 struct tevent_req **psmbreq)
461 struct tevent_req *req, *subreq;
462 struct cli_session_setup_guest_state *state;
466 req = tevent_req_create(mem_ctx, &state,
467 struct cli_session_setup_guest_state);
474 SCVAL(vwv+0, 0, 0xFF);
477 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
479 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
480 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
485 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
487 bytes = talloc_array(state, uint8_t, 0);
489 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
491 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
493 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
494 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
501 state->bytes.iov_base = (void *)bytes;
502 state->bytes.iov_len = talloc_get_size(bytes);
504 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 0, 13,
505 vwv, 1, &state->bytes);
506 if (subreq == NULL) {
510 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
515 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
516 struct tevent_context *ev,
517 struct cli_state *cli)
519 struct tevent_req *req, *subreq;
522 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
527 status = smb1cli_req_chain_submit(&subreq, 1);
528 if (!NT_STATUS_IS_OK(status)) {
529 tevent_req_nterror(req, status);
530 return tevent_req_post(req, ev);
535 static void cli_session_setup_guest_done(struct tevent_req *subreq)
537 struct tevent_req *req = tevent_req_callback_data(
538 subreq, struct tevent_req);
539 struct cli_session_setup_guest_state *state = tevent_req_data(
540 req, struct cli_session_setup_guest_state);
541 struct cli_state *cli = state->cli;
552 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
555 if (!NT_STATUS_IS_OK(status)) {
556 tevent_req_nterror(req, status);
560 inhdr = in + NBT_HDR_SIZE;
563 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
564 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
566 status = smb_bytes_talloc_string(cli,
573 if (!NT_STATUS_IS_OK(status)) {
574 tevent_req_nterror(req, status);
579 status = smb_bytes_talloc_string(cli,
586 if (!NT_STATUS_IS_OK(status)) {
587 tevent_req_nterror(req, status);
592 status = smb_bytes_talloc_string(cli,
599 if (!NT_STATUS_IS_OK(status)) {
600 tevent_req_nterror(req, status);
605 tevent_req_done(req);
608 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
610 return tevent_req_simple_recv_ntstatus(req);
613 /* The following is calculated from :
615 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
616 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
620 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
622 struct cli_sesssetup_blob_state {
623 struct tevent_context *ev;
624 struct cli_state *cli;
626 uint16_t max_blob_size;
629 struct iovec *recv_iov;
632 const uint8_t *inbuf;
639 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
640 struct tevent_req **psubreq);
641 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
643 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
644 struct tevent_context *ev,
645 struct cli_state *cli,
648 struct tevent_req *req, *subreq;
649 struct cli_sesssetup_blob_state *state;
650 uint32_t usable_space;
652 req = tevent_req_create(mem_ctx, &state,
653 struct cli_sesssetup_blob_state);
661 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
662 usable_space = UINT16_MAX;
664 usable_space = cli_state_available_size(cli,
665 BASE_SESSSETUP_BLOB_PACKET_SIZE);
668 if (usable_space == 0) {
669 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
670 "(not possible to send %u bytes)\n",
671 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
672 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
673 return tevent_req_post(req, ev);
675 state->max_blob_size = MIN(usable_space, 0xFFFF);
677 if (!cli_sesssetup_blob_next(state, &subreq)) {
678 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
679 return tevent_req_post(req, ev);
681 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
685 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
686 struct tevent_req **psubreq)
688 struct tevent_req *subreq;
691 thistime = MIN(state->blob.length, state->max_blob_size);
693 state->this_blob.data = state->blob.data;
694 state->this_blob.length = thistime;
696 state->blob.data += thistime;
697 state->blob.length -= thistime;
699 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
700 subreq = smb2cli_session_setup_send(state, state->ev,
703 state->cli->smb2.session,
705 SMB2_CAP_DFS, /* in_capabilities */
707 0, /* in_previous_session_id */
709 if (subreq == NULL) {
713 uint16_t in_buf_size = 0;
714 uint16_t in_mpx_max = 0;
715 uint16_t in_vc_num = 0;
716 uint32_t in_sess_key = 0;
717 uint32_t in_capabilities = 0;
718 const char *in_native_os = NULL;
719 const char *in_native_lm = NULL;
721 in_buf_size = CLI_BUFFER_SIZE;
722 in_mpx_max = smbXcli_conn_max_requests(state->cli->conn);
723 in_vc_num = cli_state_get_vc_num(state->cli);
724 in_sess_key = smb1cli_conn_server_session_key(state->cli->conn);
725 in_capabilities = cli_session_setup_capabilities(state->cli,
726 CAP_EXTENDED_SECURITY);
727 in_native_os = "Unix";
728 in_native_lm = "Samba";
731 * For now we keep the same values as before,
732 * we may remove these in a separate commit later.
738 subreq = smb1cli_session_setup_ext_send(state, state->ev,
741 state->cli->smb1.pid,
742 state->cli->smb1.session,
751 if (subreq == NULL) {
759 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
761 struct tevent_req *req = tevent_req_callback_data(
762 subreq, struct tevent_req);
763 struct cli_sesssetup_blob_state *state = tevent_req_data(
764 req, struct cli_sesssetup_blob_state);
765 struct cli_state *cli = state->cli;
768 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
769 status = smb2cli_session_setup_recv(subreq, state,
773 status = smb1cli_session_setup_ext_recv(subreq, state,
777 &state->out_native_os,
778 &state->out_native_lm);
781 if (!NT_STATUS_IS_OK(status)
782 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
783 tevent_req_nterror(req, status);
787 if (cli->server_os == NULL) {
788 cli->server_os = talloc_move(cli, &state->out_native_os);
790 if (cli->server_type == NULL) {
791 cli->server_type = talloc_move(cli, &state->out_native_lm);
794 state->status = status;
796 if (state->blob.length != 0) {
800 if (!cli_sesssetup_blob_next(state, &subreq)) {
804 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
807 tevent_req_done(req);
810 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
813 const uint8_t **pinbuf,
814 struct iovec **precv_iov)
816 struct cli_sesssetup_blob_state *state = tevent_req_data(
817 req, struct cli_sesssetup_blob_state);
819 struct iovec *recv_iov;
821 if (tevent_req_is_nterror(req, &status)) {
822 TALLOC_FREE(state->cli->smb2.session);
823 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
824 tevent_req_received(req);
828 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
830 *pblob = state->ret_blob;
832 if (pinbuf != NULL) {
833 *pinbuf = state->inbuf;
835 if (precv_iov != NULL) {
836 *precv_iov = recv_iov;
838 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
839 status = state->status;
840 tevent_req_received(req);
844 /****************************************************************************
845 Do a spnego/NTLMSSP encrypted session setup.
846 ****************************************************************************/
848 struct cli_session_setup_gensec_state {
849 struct tevent_context *ev;
850 struct cli_state *cli;
851 struct auth_generic_state *auth_generic;
854 const uint8_t *inbuf;
855 struct iovec *recv_iov;
859 DATA_BLOB session_key;
862 static int cli_session_setup_gensec_state_destructor(
863 struct cli_session_setup_gensec_state *state)
865 TALLOC_FREE(state->auth_generic);
866 data_blob_clear_free(&state->session_key);
870 static void cli_session_setup_gensec_local_next(struct tevent_req *req);
871 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
872 static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
873 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
874 static void cli_session_setup_gensec_ready(struct tevent_req *req);
876 static struct tevent_req *cli_session_setup_gensec_send(
877 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
878 struct cli_credentials *creds,
879 const char *target_service,
880 const char *target_hostname)
882 struct tevent_req *req;
883 struct cli_session_setup_gensec_state *state;
885 const DATA_BLOB *b = NULL;
887 req = tevent_req_create(mem_ctx, &state,
888 struct cli_session_setup_gensec_state);
895 talloc_set_destructor(
896 state, cli_session_setup_gensec_state_destructor);
898 status = auth_generic_client_prepare(state, &state->auth_generic);
899 if (tevent_req_nterror(req, status)) {
900 return tevent_req_post(req, ev);
903 status = auth_generic_set_creds(state->auth_generic, creds);
904 if (tevent_req_nterror(req, status)) {
905 return tevent_req_post(req, ev);
908 gensec_want_feature(state->auth_generic->gensec_security,
909 GENSEC_FEATURE_SESSION_KEY);
911 if (target_service != NULL) {
912 status = gensec_set_target_service(
913 state->auth_generic->gensec_security,
915 if (tevent_req_nterror(req, status)) {
916 return tevent_req_post(req, ev);
920 if (target_hostname != NULL) {
921 status = gensec_set_target_hostname(
922 state->auth_generic->gensec_security,
924 if (tevent_req_nterror(req, status)) {
925 return tevent_req_post(req, ev);
929 b = smbXcli_conn_server_gss_blob(cli->conn);
934 state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
936 status = auth_generic_client_start(state->auth_generic,
938 if (tevent_req_nterror(req, status)) {
939 return tevent_req_post(req, ev);
942 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
943 state->cli->smb2.session = smbXcli_session_create(cli,
945 if (tevent_req_nomem(state->cli->smb2.session, req)) {
946 return tevent_req_post(req, ev);
950 cli_session_setup_gensec_local_next(req);
951 if (!tevent_req_is_in_progress(req)) {
952 return tevent_req_post(req, ev);
958 static void cli_session_setup_gensec_local_next(struct tevent_req *req)
960 struct cli_session_setup_gensec_state *state =
962 struct cli_session_setup_gensec_state);
963 struct tevent_req *subreq = NULL;
965 if (state->local_ready) {
966 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
970 subreq = gensec_update_send(state, state->ev,
971 state->auth_generic->gensec_security,
973 if (tevent_req_nomem(subreq, req)) {
976 tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
979 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
981 struct tevent_req *req =
982 tevent_req_callback_data(subreq,
984 struct cli_session_setup_gensec_state *state =
986 struct cli_session_setup_gensec_state);
989 status = gensec_update_recv(subreq, state, &state->blob_out);
991 state->blob_in = data_blob_null;
992 if (!NT_STATUS_IS_OK(status) &&
993 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
995 tevent_req_nterror(req, status);
999 if (NT_STATUS_IS_OK(status)) {
1000 state->local_ready = true;
1003 if (state->local_ready && state->remote_ready) {
1004 cli_session_setup_gensec_ready(req);
1008 cli_session_setup_gensec_remote_next(req);
1011 static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
1013 struct cli_session_setup_gensec_state *state =
1014 tevent_req_data(req,
1015 struct cli_session_setup_gensec_state);
1016 struct tevent_req *subreq = NULL;
1018 if (state->remote_ready) {
1019 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1023 subreq = cli_sesssetup_blob_send(state, state->ev,
1024 state->cli, state->blob_out);
1025 if (tevent_req_nomem(subreq, req)) {
1028 tevent_req_set_callback(subreq,
1029 cli_session_setup_gensec_remote_done,
1033 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
1035 struct tevent_req *req =
1036 tevent_req_callback_data(subreq,
1038 struct cli_session_setup_gensec_state *state =
1039 tevent_req_data(req,
1040 struct cli_session_setup_gensec_state);
1043 state->inbuf = NULL;
1044 TALLOC_FREE(state->recv_iov);
1046 status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
1047 &state->inbuf, &state->recv_iov);
1048 TALLOC_FREE(subreq);
1049 data_blob_free(&state->blob_out);
1050 if (!NT_STATUS_IS_OK(status) &&
1051 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1053 tevent_req_nterror(req, status);
1057 if (NT_STATUS_IS_OK(status)) {
1058 struct smbXcli_session *session = NULL;
1059 bool is_guest = false;
1061 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1062 session = state->cli->smb2.session;
1064 session = state->cli->smb1.session;
1067 is_guest = smbXcli_session_is_guest(session);
1070 * We can't finish the gensec handshake, we don't
1071 * have a negotiated session key.
1073 * So just pretend we are completely done.
1075 * Note that smbXcli_session_is_guest()
1076 * always returns false if we require signing.
1078 state->blob_in = data_blob_null;
1079 state->local_ready = true;
1082 state->remote_ready = true;
1085 if (state->local_ready && state->remote_ready) {
1086 cli_session_setup_gensec_ready(req);
1090 cli_session_setup_gensec_local_next(req);
1093 static void cli_session_setup_gensec_ready(struct tevent_req *req)
1095 struct cli_session_setup_gensec_state *state =
1096 tevent_req_data(req,
1097 struct cli_session_setup_gensec_state);
1098 const char *server_domain = NULL;
1101 if (state->blob_in.length != 0) {
1102 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1106 if (state->blob_out.length != 0) {
1107 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1112 * gensec_ntlmssp_server_domain() returns NULL
1113 * if NTLMSSP is not used.
1115 * We can remove this later
1116 * and leave the server domain empty for SMB2 and above
1117 * in future releases.
1119 server_domain = gensec_ntlmssp_server_domain(
1120 state->auth_generic->gensec_security);
1122 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
1123 TALLOC_FREE(state->cli->server_domain);
1124 state->cli->server_domain = talloc_strdup(state->cli,
1126 if (state->cli->server_domain == NULL) {
1127 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1132 if (state->is_anonymous) {
1134 * Windows server does not set the
1135 * SMB2_SESSION_FLAG_IS_NULL flag.
1137 * This fix makes sure we do not try
1138 * to verify a signature on the final
1139 * session setup response.
1141 tevent_req_done(req);
1145 status = gensec_session_key(state->auth_generic->gensec_security,
1146 state, &state->session_key);
1147 if (tevent_req_nterror(req, status)) {
1151 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1152 struct smbXcli_session *session = state->cli->smb2.session;
1154 status = smb2cli_session_set_session_key(session,
1157 if (tevent_req_nterror(req, status)) {
1161 struct smbXcli_session *session = state->cli->smb1.session;
1164 status = smb1cli_session_set_session_key(session,
1165 state->session_key);
1166 if (tevent_req_nterror(req, status)) {
1170 active = smb1cli_conn_activate_signing(state->cli->conn,
1176 ok = smb1cli_conn_check_signing(state->cli->conn,
1179 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1185 tevent_req_done(req);
1188 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1190 struct cli_session_setup_gensec_state *state =
1191 tevent_req_data(req,
1192 struct cli_session_setup_gensec_state);
1195 if (tevent_req_is_nterror(req, &status)) {
1196 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1199 return NT_STATUS_OK;
1202 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1203 const char *principal)
1207 account = talloc_strdup(mem_ctx, principal);
1208 if (account == NULL) {
1211 p = strchr_m(account, '@');
1218 /****************************************************************************
1219 Do a spnego encrypted session setup.
1221 user_domain: The shortname of the domain the user/machine is a member of.
1222 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1223 ****************************************************************************/
1225 struct cli_session_setup_spnego_state {
1229 static void cli_session_setup_spnego_done(struct tevent_req *subreq);
1231 static struct tevent_req *cli_session_setup_spnego_send(
1232 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1233 struct cli_credentials *creds)
1235 struct tevent_req *req, *subreq;
1236 struct cli_session_setup_spnego_state *state;
1237 const char *target_service = NULL;
1238 const char *target_hostname = NULL;
1241 req = tevent_req_create(mem_ctx, &state,
1242 struct cli_session_setup_spnego_state);
1247 target_service = "cifs";
1248 target_hostname = smbXcli_conn_remote_name(cli->conn);
1250 status = cli_session_creds_prepare_krb5(cli, creds);
1251 if (tevent_req_nterror(req, status)) {
1252 return tevent_req_post(req, ev);;
1255 subreq = cli_session_setup_gensec_send(state, ev, cli, creds,
1256 target_service, target_hostname);
1257 if (tevent_req_nomem(subreq, req)) {
1258 return tevent_req_post(req, ev);
1260 tevent_req_set_callback(
1261 subreq, cli_session_setup_spnego_done, req);
1265 static void cli_session_setup_spnego_done(struct tevent_req *subreq)
1267 struct tevent_req *req = tevent_req_callback_data(
1268 subreq, struct tevent_req);
1271 status = cli_session_setup_gensec_recv(subreq);
1272 TALLOC_FREE(subreq);
1273 if (tevent_req_nterror(req, status)) {
1277 tevent_req_done(req);
1280 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1282 struct cli_session_setup_spnego_state *state = tevent_req_data(
1283 req, struct cli_session_setup_spnego_state);
1286 if (tevent_req_is_nterror(req, &status)) {
1287 state->result = ADS_ERROR_NT(status);
1290 return state->result;
1293 struct cli_session_setup_creds_state {
1294 struct cli_state *cli;
1295 DATA_BLOB apassword_blob;
1296 DATA_BLOB upassword_blob;
1297 DATA_BLOB lm_session_key;
1298 DATA_BLOB session_key;
1299 char *out_native_os;
1300 char *out_native_lm;
1301 char *out_primary_domain;
1304 static void cli_session_setup_creds_cleanup(struct tevent_req *req,
1305 enum tevent_req_state req_state)
1307 struct cli_session_setup_creds_state *state = tevent_req_data(
1308 req, struct cli_session_setup_creds_state);
1310 if (req_state != TEVENT_REQ_RECEIVED) {
1315 * We only call data_blob_clear() as
1316 * some of the blobs point to the same memory.
1318 * We let the talloc hierachy free the memory.
1320 data_blob_clear(&state->apassword_blob);
1321 data_blob_clear(&state->upassword_blob);
1322 data_blob_clear(&state->lm_session_key);
1323 data_blob_clear(&state->session_key);
1324 ZERO_STRUCTP(state);
1327 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq);
1328 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq);
1329 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq);
1331 /****************************************************************************
1332 Send a session setup. The username and workgroup is in UNIX character
1333 format and must be converted to DOS codepage format before sending. If the
1334 password is in plaintext, the same should be done.
1335 ****************************************************************************/
1337 struct tevent_req *cli_session_setup_creds_send(TALLOC_CTX *mem_ctx,
1338 struct tevent_context *ev,
1339 struct cli_state *cli,
1340 struct cli_credentials *creds)
1342 struct tevent_req *req, *subreq;
1343 struct cli_session_setup_creds_state *state;
1344 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1345 bool use_spnego = false;
1347 enum credentials_use_kerberos krb5_state;
1348 uint32_t gensec_features;
1349 const char *username = "";
1350 const char *domain = "";
1351 DATA_BLOB target_info = data_blob_null;
1352 DATA_BLOB challenge = data_blob_null;
1353 uint16_t in_buf_size = 0;
1354 uint16_t in_mpx_max = 0;
1355 uint16_t in_vc_num = 0;
1356 uint32_t in_sess_key = 0;
1357 const char *in_native_os = NULL;
1358 const char *in_native_lm = NULL;
1361 req = tevent_req_create(mem_ctx, &state,
1362 struct cli_session_setup_creds_state);
1368 tevent_req_set_cleanup_fn(req, cli_session_setup_creds_cleanup);
1370 krb5_state = cli_credentials_get_kerberos_state(creds);
1371 gensec_features = cli_credentials_get_gensec_features(creds);
1373 switch (krb5_state) {
1374 case CRED_MUST_USE_KERBEROS:
1375 cli->use_kerberos = true;
1376 cli->fallback_after_kerberos = false;
1378 case CRED_AUTO_USE_KERBEROS:
1379 cli->use_kerberos = true;
1380 cli->fallback_after_kerberos = true;
1382 case CRED_DONT_USE_KERBEROS:
1383 cli->use_kerberos = false;
1384 cli->fallback_after_kerberos = false;
1388 if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
1389 cli->use_ccache = true;
1391 cli->use_ccache = false;
1395 * Now work out what sort of session setup we are going to
1396 * do. I have split this into separate functions to make the flow a bit
1397 * easier to understand (tridge).
1399 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
1401 } else if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1403 } else if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
1405 * if the server supports extended security then use SPNEGO
1406 * even for anonymous connections.
1414 subreq = cli_session_setup_spnego_send(
1415 state, ev, cli, creds);
1416 if (tevent_req_nomem(subreq, req)) {
1417 return tevent_req_post(req, ev);
1419 tevent_req_set_callback(subreq, cli_session_setup_creds_done_spnego,
1424 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1426 * SessionSetupAndX was introduced by LANMAN 1.0. So we skip
1427 * this step against older servers.
1429 tevent_req_done(req);
1430 return tevent_req_post(req, ev);
1433 if (cli_credentials_is_anonymous(creds)) {
1435 * Do an anonymous session setup
1437 goto non_spnego_creds_done;
1440 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
1442 * Do an anonymous session setup,
1443 * the password is passed via the tree connect.
1445 goto non_spnego_creds_done;
1448 cli_credentials_get_ntlm_username_domain(creds, state,
1451 if (tevent_req_nomem(username, req)) {
1452 return tevent_req_post(req, ev);
1454 if (tevent_req_nomem(domain, req)) {
1455 return tevent_req_post(req, ev);
1458 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1459 bool use_unicode = smbXcli_conn_use_unicode(cli->conn);
1460 uint8_t *bytes = NULL;
1461 size_t bytes_len = 0;
1462 const char *pw = cli_credentials_get_password(creds);
1468 pw_len = strlen(pw) + 1;
1470 if (!lp_client_plaintext_auth()) {
1471 DEBUG(1, ("Server requested PLAINTEXT password but "
1472 "'client plaintext auth = no'\n"));
1473 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1474 return tevent_req_post(req, ev);
1477 bytes = talloc_array(state, uint8_t, 0);
1478 bytes = trans2_bytes_push_str(bytes, use_unicode,
1479 pw, pw_len, &bytes_len);
1480 if (tevent_req_nomem(bytes, req)) {
1481 return tevent_req_post(req, ev);
1486 * CAP_UNICODE, can only be negotiated by NT1.
1488 state->upassword_blob = data_blob_const(bytes,
1491 state->apassword_blob = data_blob_const(bytes,
1495 goto non_spnego_creds_done;
1498 challenge = data_blob_const(smb1cli_conn_server_challenge(cli->conn), 8);
1500 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1501 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
1503 * Don't send an NTLMv2 response without NTLMSSP if we
1504 * want to use spnego support.
1506 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
1507 " but 'client use spnego = yes'"
1508 " and 'client ntlmv2 auth = yes' is set\n"));
1509 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1510 return tevent_req_post(req, ev);
1513 if (lp_client_ntlmv2_auth()) {
1514 flags |= CLI_CRED_NTLMv2_AUTH;
1517 * note that the 'domain' here is a best
1518 * guess - we don't know the server's domain
1519 * at this point. Windows clients also don't
1522 target_info = NTLMv2_generate_names_blob(state,
1525 if (tevent_req_nomem(target_info.data, req)) {
1526 return tevent_req_post(req, ev);
1529 flags |= CLI_CRED_NTLM_AUTH;
1530 if (lp_client_lanman_auth()) {
1531 flags |= CLI_CRED_LANMAN_AUTH;
1535 if (!lp_client_lanman_auth()) {
1536 DEBUG(1, ("Server requested user level LM password but "
1537 "'client lanman auth = no' is set.\n"));
1538 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1539 return tevent_req_post(req, ev);
1542 flags |= CLI_CRED_LANMAN_AUTH;
1545 status = cli_credentials_get_ntlm_response(creds, state, &flags,
1548 &state->apassword_blob,
1549 &state->upassword_blob,
1550 &state->lm_session_key,
1551 &state->session_key);
1552 if (tevent_req_nterror(req, status)) {
1553 return tevent_req_post(req, ev);
1556 non_spnego_creds_done:
1558 in_buf_size = CLI_BUFFER_SIZE;
1559 in_mpx_max = smbXcli_conn_max_requests(cli->conn);
1560 in_vc_num = cli_state_get_vc_num(cli);
1561 in_sess_key = smb1cli_conn_server_session_key(cli->conn);
1562 in_native_os = "Unix";
1563 in_native_lm = "Samba";
1565 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1566 uint32_t in_capabilities = 0;
1568 in_capabilities = cli_session_setup_capabilities(cli, 0);
1571 * For now we keep the same values as before,
1572 * we may remove these in a separate commit later.
1576 subreq = smb1cli_session_setup_nt1_send(state, ev,
1587 state->apassword_blob,
1588 state->upassword_blob,
1592 if (tevent_req_nomem(subreq, req)) {
1593 return tevent_req_post(req, ev);
1595 tevent_req_set_callback(subreq, cli_session_setup_creds_done_nt1,
1601 * For now we keep the same values as before,
1602 * we may remove these in a separate commit later.
1607 subreq = smb1cli_session_setup_lm21_send(state, ev,
1618 state->apassword_blob,
1621 if (tevent_req_nomem(subreq, req)) {
1622 return tevent_req_post(req, ev);
1624 tevent_req_set_callback(subreq, cli_session_setup_creds_done_lm21,
1629 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq)
1631 struct tevent_req *req = tevent_req_callback_data(
1632 subreq, struct tevent_req);
1635 status = cli_session_setup_spnego_recv(subreq);
1636 TALLOC_FREE(subreq);
1637 if (!ADS_ERR_OK(status)) {
1638 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1639 tevent_req_nterror(req, ads_ntstatus(status));
1642 tevent_req_done(req);
1645 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq)
1647 struct tevent_req *req = tevent_req_callback_data(
1648 subreq, struct tevent_req);
1649 struct cli_session_setup_creds_state *state = tevent_req_data(
1650 req, struct cli_session_setup_creds_state);
1651 struct cli_state *cli = state->cli;
1653 struct iovec *recv_iov = NULL;
1654 const uint8_t *inbuf = NULL;
1657 status = smb1cli_session_setup_nt1_recv(subreq, state,
1660 &state->out_native_os,
1661 &state->out_native_lm,
1662 &state->out_primary_domain);
1663 TALLOC_FREE(subreq);
1664 if (!NT_STATUS_IS_OK(status)) {
1665 DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
1666 tevent_req_nterror(req, status);
1670 if (cli->server_os == NULL) {
1671 cli->server_os = talloc_move(cli, &state->out_native_os);
1673 if (cli->server_type == NULL) {
1674 cli->server_type = talloc_move(cli, &state->out_native_lm);
1676 if (cli->server_domain == NULL) {
1677 cli->server_domain = talloc_move(cli, &state->out_primary_domain);
1680 ok = smb1cli_conn_activate_signing(cli->conn,
1682 state->upassword_blob);
1684 ok = smb1cli_conn_check_signing(cli->conn, inbuf, 1);
1686 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1691 if (state->session_key.data) {
1692 struct smbXcli_session *session = cli->smb1.session;
1694 status = smb1cli_session_set_session_key(session,
1695 state->session_key);
1696 if (tevent_req_nterror(req, status)) {
1701 tevent_req_done(req);
1704 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq)
1706 struct tevent_req *req = tevent_req_callback_data(
1707 subreq, struct tevent_req);
1708 struct cli_session_setup_creds_state *state = tevent_req_data(
1709 req, struct cli_session_setup_creds_state);
1710 struct cli_state *cli = state->cli;
1713 status = smb1cli_session_setup_lm21_recv(subreq, state,
1714 &state->out_native_os,
1715 &state->out_native_lm);
1716 TALLOC_FREE(subreq);
1717 if (!NT_STATUS_IS_OK(status)) {
1718 DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
1719 tevent_req_nterror(req, status);
1723 if (cli->server_os == NULL) {
1724 cli->server_os = talloc_move(cli, &state->out_native_os);
1726 if (cli->server_type == NULL) {
1727 cli->server_type = talloc_move(cli, &state->out_native_lm);
1730 tevent_req_done(req);
1733 NTSTATUS cli_session_setup_creds_recv(struct tevent_req *req)
1735 return tevent_req_simple_recv_ntstatus(req);
1738 NTSTATUS cli_session_setup_creds(struct cli_state *cli,
1739 struct cli_credentials *creds)
1741 struct tevent_context *ev;
1742 struct tevent_req *req;
1743 NTSTATUS status = NT_STATUS_NO_MEMORY;
1745 if (smbXcli_conn_has_async_calls(cli->conn)) {
1746 return NT_STATUS_INVALID_PARAMETER;
1748 ev = samba_tevent_context_init(talloc_tos());
1752 req = cli_session_setup_creds_send(ev, ev, cli, creds);
1756 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1759 status = cli_session_setup_creds_recv(req);
1765 NTSTATUS cli_session_setup_anon(struct cli_state *cli)
1767 NTSTATUS status = NT_STATUS_NO_MEMORY;
1768 struct cli_credentials *creds = NULL;
1770 creds = cli_credentials_init_anon(cli);
1771 if (creds == NULL) {
1772 return NT_STATUS_NO_MEMORY;
1775 status = cli_session_setup_creds(cli, creds);
1777 if (!NT_STATUS_IS_OK(status)) {
1781 return NT_STATUS_OK;
1784 /****************************************************************************
1786 *****************************************************************************/
1788 struct cli_ulogoff_state {
1789 struct cli_state *cli;
1793 static void cli_ulogoff_done(struct tevent_req *subreq);
1795 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1796 struct tevent_context *ev,
1797 struct cli_state *cli)
1799 struct tevent_req *req, *subreq;
1800 struct cli_ulogoff_state *state;
1802 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1808 SCVAL(state->vwv+0, 0, 0xFF);
1809 SCVAL(state->vwv+1, 0, 0);
1810 SSVAL(state->vwv+2, 0, 0);
1812 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
1814 if (tevent_req_nomem(subreq, req)) {
1815 return tevent_req_post(req, ev);
1817 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1821 static void cli_ulogoff_done(struct tevent_req *subreq)
1823 struct tevent_req *req = tevent_req_callback_data(
1824 subreq, struct tevent_req);
1825 struct cli_ulogoff_state *state = tevent_req_data(
1826 req, struct cli_ulogoff_state);
1829 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1830 if (!NT_STATUS_IS_OK(status)) {
1831 tevent_req_nterror(req, status);
1834 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1835 tevent_req_done(req);
1838 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1840 return tevent_req_simple_recv_ntstatus(req);
1843 NTSTATUS cli_ulogoff(struct cli_state *cli)
1845 struct tevent_context *ev;
1846 struct tevent_req *req;
1847 NTSTATUS status = NT_STATUS_NO_MEMORY;
1849 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1850 status = smb2cli_logoff(cli->conn,
1853 if (!NT_STATUS_IS_OK(status)) {
1856 smb2cli_session_set_id_and_flags(cli->smb2.session,
1858 return NT_STATUS_OK;
1861 if (smbXcli_conn_has_async_calls(cli->conn)) {
1862 return NT_STATUS_INVALID_PARAMETER;
1864 ev = samba_tevent_context_init(talloc_tos());
1868 req = cli_ulogoff_send(ev, ev, cli);
1872 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1875 status = cli_ulogoff_recv(req);
1881 /****************************************************************************
1883 ****************************************************************************/
1885 struct cli_tcon_andx_state {
1886 struct cli_state *cli;
1891 static void cli_tcon_andx_done(struct tevent_req *subreq);
1893 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1894 struct tevent_context *ev,
1895 struct cli_state *cli,
1896 const char *share, const char *dev,
1897 const char *pass, int passlen,
1898 struct tevent_req **psmbreq)
1900 struct tevent_req *req, *subreq;
1901 struct cli_tcon_andx_state *state;
1906 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1907 uint16_t tcon_flags = 0;
1911 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1918 cli->share = talloc_strdup(cli, share);
1923 /* in user level security don't send a password now */
1924 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1927 } else if (pass == NULL) {
1928 DEBUG(1, ("Server not using user level security and no "
1929 "password supplied.\n"));
1933 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1934 *pass && passlen != 24) {
1935 if (!lp_client_lanman_auth()) {
1936 DEBUG(1, ("Server requested LANMAN password "
1937 "(share-level security) but "
1938 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
1943 * Non-encrypted passwords - convert to DOS codepage before
1946 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
1948 pass = (const char *)p24;
1950 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1951 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1955 if (!lp_client_plaintext_auth() && (*pass)) {
1956 DEBUG(1, ("Server requested PLAINTEXT "
1958 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
1963 * Non-encrypted passwords - convert to DOS codepage
1966 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
1967 if (tevent_req_nomem(tmp_pass, req)) {
1968 return tevent_req_post(req, ev);
1970 tmp_pass = trans2_bytes_push_str(tmp_pass,
1971 false, /* always DOS */
1975 if (tevent_req_nomem(tmp_pass, req)) {
1976 return tevent_req_post(req, ev);
1978 pass = (const char *)tmp_pass;
1979 passlen = talloc_get_size(tmp_pass);
1983 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
1984 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
1986 SCVAL(vwv+0, 0, 0xFF);
1989 SSVAL(vwv+2, 0, tcon_flags);
1990 SSVAL(vwv+3, 0, passlen);
1992 if (passlen && pass) {
1993 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
1995 bytes = talloc_array(state, uint8_t, 0);
2001 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2002 smbXcli_conn_remote_name(cli->conn), share);
2007 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2012 * Add the devicetype
2014 tmp = talloc_strdup_upper(talloc_tos(), dev);
2019 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2022 if (bytes == NULL) {
2027 state->bytes.iov_base = (void *)bytes;
2028 state->bytes.iov_len = talloc_get_size(bytes);
2030 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
2032 if (subreq == NULL) {
2036 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2041 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2042 return tevent_req_post(req, ev);
2045 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2046 struct tevent_context *ev,
2047 struct cli_state *cli,
2048 const char *share, const char *dev,
2049 const char *pass, int passlen)
2051 struct tevent_req *req, *subreq;
2054 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2059 if (subreq == NULL) {
2062 status = smb1cli_req_chain_submit(&subreq, 1);
2063 if (!NT_STATUS_IS_OK(status)) {
2064 tevent_req_nterror(req, status);
2065 return tevent_req_post(req, ev);
2070 static void cli_tcon_andx_done(struct tevent_req *subreq)
2072 struct tevent_req *req = tevent_req_callback_data(
2073 subreq, struct tevent_req);
2074 struct cli_tcon_andx_state *state = tevent_req_data(
2075 req, struct cli_tcon_andx_state);
2076 struct cli_state *cli = state->cli;
2084 uint16_t optional_support = 0;
2086 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2087 &num_bytes, &bytes);
2088 TALLOC_FREE(subreq);
2089 if (!NT_STATUS_IS_OK(status)) {
2090 tevent_req_nterror(req, status);
2094 inhdr = in + NBT_HDR_SIZE;
2097 if (clistr_pull_talloc(cli,
2098 (const char *)inhdr,
2099 SVAL(inhdr, HDR_FLG2),
2103 STR_TERMINATE|STR_ASCII) == -1) {
2104 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2108 cli->dev = talloc_strdup(cli, "");
2109 if (cli->dev == NULL) {
2110 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2115 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2116 /* almost certainly win95 - enable bug fixes */
2121 * Make sure that we have the optional support 16-bit field. WCT > 2.
2122 * Avoids issues when connecting to Win9x boxes sharing files
2125 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2126 optional_support = SVAL(vwv+2, 0);
2129 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2130 smb1cli_session_protect_session_key(cli->smb1.session);
2133 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2134 SVAL(inhdr, HDR_TID),
2136 0, /* maximal_access */
2137 0, /* guest_maximal_access */
2139 NULL); /* fs_type */
2141 tevent_req_done(req);
2144 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2146 return tevent_req_simple_recv_ntstatus(req);
2149 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2150 const char *dev, const char *pass, int passlen)
2152 TALLOC_CTX *frame = talloc_stackframe();
2153 struct tevent_context *ev;
2154 struct tevent_req *req;
2155 NTSTATUS status = NT_STATUS_NO_MEMORY;
2157 if (smbXcli_conn_has_async_calls(cli->conn)) {
2159 * Can't use sync call while an async call is in flight
2161 status = NT_STATUS_INVALID_PARAMETER;
2165 ev = samba_tevent_context_init(frame);
2170 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2175 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2179 status = cli_tcon_andx_recv(req);
2185 struct cli_tree_connect_state {
2186 struct cli_state *cli;
2189 static struct tevent_req *cli_raw_tcon_send(
2190 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2191 const char *service, const char *pass, const char *dev);
2192 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2193 uint16_t *max_xmit, uint16_t *tid);
2195 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2196 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2197 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2199 static struct tevent_req *cli_tree_connect_send(
2200 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2201 const char *share, const char *dev, const char *pass)
2203 struct tevent_req *req, *subreq;
2204 struct cli_tree_connect_state *state;
2210 passlen = strlen(pass) + 1;
2212 req = tevent_req_create(mem_ctx, &state,
2213 struct cli_tree_connect_state);
2219 cli->share = talloc_strdup(cli, share);
2220 if (tevent_req_nomem(cli->share, req)) {
2221 return tevent_req_post(req, ev);
2224 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2227 cli->smb2.tcon = smbXcli_tcon_create(cli);
2228 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2229 return tevent_req_post(req, ev);
2232 unc = talloc_asprintf(state, "\\\\%s\\%s",
2233 smbXcli_conn_remote_name(cli->conn),
2235 if (tevent_req_nomem(unc, req)) {
2236 return tevent_req_post(req, ev);
2239 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2240 cli->smb2.session, cli->smb2.tcon,
2243 if (tevent_req_nomem(subreq, req)) {
2244 return tevent_req_post(req, ev);
2246 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2251 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2252 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2254 if (tevent_req_nomem(subreq, req)) {
2255 return tevent_req_post(req, ev);
2257 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2262 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2263 if (tevent_req_nomem(subreq, req)) {
2264 return tevent_req_post(req, ev);
2266 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2271 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2273 tevent_req_simple_finish_ntstatus(
2274 subreq, smb2cli_tcon_recv(subreq));
2277 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2279 tevent_req_simple_finish_ntstatus(
2280 subreq, cli_tcon_andx_recv(subreq));
2283 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2285 struct tevent_req *req = tevent_req_callback_data(
2286 subreq, struct tevent_req);
2287 struct cli_tree_connect_state *state = tevent_req_data(
2288 req, struct cli_tree_connect_state);
2290 uint16_t max_xmit = 0;
2293 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2294 if (tevent_req_nterror(req, status)) {
2298 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2300 0, /* optional_support */
2301 0, /* maximal_access */
2302 0, /* guest_maximal_access */
2304 NULL); /* fs_type */
2306 tevent_req_done(req);
2309 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2311 return tevent_req_simple_recv_ntstatus(req);
2314 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2315 const char *dev, const char *pass)
2317 struct tevent_context *ev;
2318 struct tevent_req *req;
2319 NTSTATUS status = NT_STATUS_NO_MEMORY;
2321 if (smbXcli_conn_has_async_calls(cli->conn)) {
2322 return NT_STATUS_INVALID_PARAMETER;
2324 ev = samba_tevent_context_init(talloc_tos());
2328 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass);
2332 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2335 status = cli_tree_connect_recv(req);
2341 NTSTATUS cli_tree_connect_creds(struct cli_state *cli,
2342 const char *share, const char *dev,
2343 struct cli_credentials *creds)
2345 const char *pw = NULL;
2347 if (creds != NULL) {
2348 pw = cli_credentials_get_password(creds);
2351 return cli_tree_connect(cli, share, dev, pw);
2354 /****************************************************************************
2355 Send a tree disconnect.
2356 ****************************************************************************/
2358 struct cli_tdis_state {
2359 struct cli_state *cli;
2362 static void cli_tdis_done(struct tevent_req *subreq);
2364 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2365 struct tevent_context *ev,
2366 struct cli_state *cli)
2368 struct tevent_req *req, *subreq;
2369 struct cli_tdis_state *state;
2371 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2377 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2378 if (tevent_req_nomem(subreq, req)) {
2379 return tevent_req_post(req, ev);
2381 tevent_req_set_callback(subreq, cli_tdis_done, req);
2385 static void cli_tdis_done(struct tevent_req *subreq)
2387 struct tevent_req *req = tevent_req_callback_data(
2388 subreq, struct tevent_req);
2389 struct cli_tdis_state *state = tevent_req_data(
2390 req, struct cli_tdis_state);
2393 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2394 TALLOC_FREE(subreq);
2395 if (!NT_STATUS_IS_OK(status)) {
2396 tevent_req_nterror(req, status);
2399 cli_state_set_tid(state->cli, UINT16_MAX);
2400 tevent_req_done(req);
2403 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2405 return tevent_req_simple_recv_ntstatus(req);
2408 NTSTATUS cli_tdis(struct cli_state *cli)
2410 struct tevent_context *ev;
2411 struct tevent_req *req;
2412 NTSTATUS status = NT_STATUS_NO_MEMORY;
2414 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2415 return smb2cli_tdis(cli->conn,
2421 if (smbXcli_conn_has_async_calls(cli->conn)) {
2422 return NT_STATUS_INVALID_PARAMETER;
2424 ev = samba_tevent_context_init(talloc_tos());
2428 req = cli_tdis_send(ev, ev, cli);
2432 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2435 status = cli_tdis_recv(req);
2441 struct cli_connect_sock_state {
2442 const char **called_names;
2443 const char **calling_names;
2449 static void cli_connect_sock_done(struct tevent_req *subreq);
2452 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2456 static struct tevent_req *cli_connect_sock_send(
2457 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2458 const char *host, int name_type, const struct sockaddr_storage *pss,
2459 const char *myname, uint16_t port)
2461 struct tevent_req *req, *subreq;
2462 struct cli_connect_sock_state *state;
2464 struct sockaddr_storage *addrs;
2465 unsigned i, num_addrs;
2468 req = tevent_req_create(mem_ctx, &state,
2469 struct cli_connect_sock_state);
2474 prog = getenv("LIBSMB_PROG");
2476 state->fd = sock_exec(prog);
2477 if (state->fd == -1) {
2478 status = map_nt_error_from_unix(errno);
2479 tevent_req_nterror(req, status);
2482 tevent_req_done(req);
2484 return tevent_req_post(req, ev);
2487 if ((pss == NULL) || is_zero_addr(pss)) {
2490 * Here we cheat. resolve_name_list is not async at all. So
2491 * this call will only be really async if the name lookup has
2492 * been done externally.
2495 status = resolve_name_list(state, host, name_type,
2496 &addrs, &num_addrs);
2497 if (!NT_STATUS_IS_OK(status)) {
2498 tevent_req_nterror(req, status);
2499 return tevent_req_post(req, ev);
2502 addrs = talloc_array(state, struct sockaddr_storage, 1);
2503 if (tevent_req_nomem(addrs, req)) {
2504 return tevent_req_post(req, ev);
2510 state->called_names = talloc_array(state, const char *, num_addrs);
2511 if (tevent_req_nomem(state->called_names, req)) {
2512 return tevent_req_post(req, ev);
2514 state->called_types = talloc_array(state, int, num_addrs);
2515 if (tevent_req_nomem(state->called_types, req)) {
2516 return tevent_req_post(req, ev);
2518 state->calling_names = talloc_array(state, const char *, num_addrs);
2519 if (tevent_req_nomem(state->calling_names, req)) {
2520 return tevent_req_post(req, ev);
2522 for (i=0; i<num_addrs; i++) {
2523 state->called_names[i] = host;
2524 state->called_types[i] = name_type;
2525 state->calling_names[i] = myname;
2528 subreq = smbsock_any_connect_send(
2529 state, ev, addrs, state->called_names, state->called_types,
2530 state->calling_names, NULL, num_addrs, port);
2531 if (tevent_req_nomem(subreq, req)) {
2532 return tevent_req_post(req, ev);
2534 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2538 static void cli_connect_sock_done(struct tevent_req *subreq)
2540 struct tevent_req *req = tevent_req_callback_data(
2541 subreq, struct tevent_req);
2542 struct cli_connect_sock_state *state = tevent_req_data(
2543 req, struct cli_connect_sock_state);
2546 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2548 TALLOC_FREE(subreq);
2549 if (tevent_req_nterror(req, status)) {
2552 set_socket_options(state->fd, lp_socket_options());
2553 tevent_req_done(req);
2556 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2557 int *pfd, uint16_t *pport)
2559 struct cli_connect_sock_state *state = tevent_req_data(
2560 req, struct cli_connect_sock_state);
2563 if (tevent_req_is_nterror(req, &status)) {
2567 *pport = state->port;
2568 return NT_STATUS_OK;
2571 struct cli_connect_nb_state {
2572 const char *desthost;
2575 struct cli_state *cli;
2578 static void cli_connect_nb_done(struct tevent_req *subreq);
2580 static struct tevent_req *cli_connect_nb_send(
2581 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2582 const char *host, const struct sockaddr_storage *dest_ss,
2583 uint16_t port, int name_type, const char *myname,
2584 int signing_state, int flags)
2586 struct tevent_req *req, *subreq;
2587 struct cli_connect_nb_state *state;
2589 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2593 state->signing_state = signing_state;
2594 state->flags = flags;
2597 char *p = strchr(host, '#');
2600 name_type = strtol(p+1, NULL, 16);
2601 host = talloc_strndup(state, host, p - host);
2602 if (tevent_req_nomem(host, req)) {
2603 return tevent_req_post(req, ev);
2607 state->desthost = host;
2608 } else if (dest_ss != NULL) {
2609 state->desthost = print_canonical_sockaddr(state, dest_ss);
2610 if (tevent_req_nomem(state->desthost, req)) {
2611 return tevent_req_post(req, ev);
2614 /* No host or dest_ss given. Error out. */
2615 tevent_req_error(req, EINVAL);
2616 return tevent_req_post(req, ev);
2619 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2621 if (tevent_req_nomem(subreq, req)) {
2622 return tevent_req_post(req, ev);
2624 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2628 static void cli_connect_nb_done(struct tevent_req *subreq)
2630 struct tevent_req *req = tevent_req_callback_data(
2631 subreq, struct tevent_req);
2632 struct cli_connect_nb_state *state = tevent_req_data(
2633 req, struct cli_connect_nb_state);
2638 status = cli_connect_sock_recv(subreq, &fd, &port);
2639 TALLOC_FREE(subreq);
2640 if (tevent_req_nterror(req, status)) {
2644 state->cli = cli_state_create(state, fd, state->desthost, NULL,
2645 state->signing_state, state->flags);
2646 if (tevent_req_nomem(state->cli, req)) {
2650 tevent_req_done(req);
2653 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
2654 struct cli_state **pcli)
2656 struct cli_connect_nb_state *state = tevent_req_data(
2657 req, struct cli_connect_nb_state);
2660 if (tevent_req_is_nterror(req, &status)) {
2663 *pcli = talloc_move(NULL, &state->cli);
2664 return NT_STATUS_OK;
2667 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2668 uint16_t port, int name_type, const char *myname,
2669 int signing_state, int flags, struct cli_state **pcli)
2671 struct tevent_context *ev;
2672 struct tevent_req *req;
2673 NTSTATUS status = NT_STATUS_NO_MEMORY;
2675 ev = samba_tevent_context_init(talloc_tos());
2679 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
2680 myname, signing_state, flags);
2684 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
2687 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2690 status = cli_connect_nb_recv(req, pcli);
2696 struct cli_start_connection_state {
2697 struct tevent_context *ev;
2698 struct cli_state *cli;
2703 static void cli_start_connection_connected(struct tevent_req *subreq);
2704 static void cli_start_connection_done(struct tevent_req *subreq);
2707 establishes a connection to after the negprot.
2708 @param output_cli A fully initialised cli structure, non-null only on success
2709 @param dest_host The netbios name of the remote host
2710 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2711 @param port (optional) The destination port (0 for default)
2714 static struct tevent_req *cli_start_connection_send(
2715 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2716 const char *my_name, const char *dest_host,
2717 const struct sockaddr_storage *dest_ss, int port,
2718 int signing_state, int flags)
2720 struct tevent_req *req, *subreq;
2721 struct cli_start_connection_state *state;
2723 req = tevent_req_create(mem_ctx, &state,
2724 struct cli_start_connection_state);
2730 if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
2731 state->min_protocol = lp_client_ipc_min_protocol();
2732 state->max_protocol = lp_client_ipc_max_protocol();
2734 state->min_protocol = lp_client_min_protocol();
2735 state->max_protocol = lp_client_max_protocol();
2738 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
2739 0x20, my_name, signing_state, flags);
2740 if (tevent_req_nomem(subreq, req)) {
2741 return tevent_req_post(req, ev);
2743 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
2747 static void cli_start_connection_connected(struct tevent_req *subreq)
2749 struct tevent_req *req = tevent_req_callback_data(
2750 subreq, struct tevent_req);
2751 struct cli_start_connection_state *state = tevent_req_data(
2752 req, struct cli_start_connection_state);
2755 status = cli_connect_nb_recv(subreq, &state->cli);
2756 TALLOC_FREE(subreq);
2757 if (tevent_req_nterror(req, status)) {
2761 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
2762 state->cli->timeout,
2763 state->min_protocol,
2764 state->max_protocol,
2765 WINDOWS_CLIENT_PURE_SMB2_NEGPROT_INITIAL_CREDIT_ASK);
2766 if (tevent_req_nomem(subreq, req)) {
2769 tevent_req_set_callback(subreq, cli_start_connection_done, req);
2772 static void cli_start_connection_done(struct tevent_req *subreq)
2774 struct tevent_req *req = tevent_req_callback_data(
2775 subreq, struct tevent_req);
2776 struct cli_start_connection_state *state = tevent_req_data(
2777 req, struct cli_start_connection_state);
2780 status = smbXcli_negprot_recv(subreq);
2781 TALLOC_FREE(subreq);
2782 if (tevent_req_nterror(req, status)) {
2786 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
2787 /* Ensure we ask for some initial credits. */
2788 smb2cli_conn_set_max_credits(state->cli->conn,
2789 DEFAULT_SMB2_MAX_CREDITS);
2792 tevent_req_done(req);
2795 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
2796 struct cli_state **output_cli)
2798 struct cli_start_connection_state *state = tevent_req_data(
2799 req, struct cli_start_connection_state);
2802 if (tevent_req_is_nterror(req, &status)) {
2805 *output_cli = state->cli;
2807 return NT_STATUS_OK;
2810 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2811 const char *my_name,
2812 const char *dest_host,
2813 const struct sockaddr_storage *dest_ss, int port,
2814 int signing_state, int flags)
2816 struct tevent_context *ev;
2817 struct tevent_req *req;
2818 NTSTATUS status = NT_STATUS_NO_MEMORY;
2820 ev = samba_tevent_context_init(talloc_tos());
2824 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
2825 port, signing_state, flags);
2829 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2832 status = cli_start_connection_recv(req, output_cli);
2838 struct cli_smb1_setup_encryption_blob_state {
2843 uint16_t enc_ctx_id;
2846 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq);
2848 static struct tevent_req *cli_smb1_setup_encryption_blob_send(TALLOC_CTX *mem_ctx,
2849 struct tevent_context *ev,
2850 struct cli_state *cli,
2853 struct tevent_req *req = NULL;
2854 struct cli_smb1_setup_encryption_blob_state *state = NULL;
2855 struct tevent_req *subreq = NULL;
2857 req = tevent_req_create(mem_ctx, &state,
2858 struct cli_smb1_setup_encryption_blob_state);
2863 if (in.length > CLI_BUFFER_SIZE) {
2864 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2865 return tevent_req_post(req, ev);
2868 SSVAL(state->setup+0, 0, TRANSACT2_SETFSINFO);
2869 SSVAL(state->param, 0, 0);
2870 SSVAL(state->param, 2, SMB_REQUEST_TRANSPORT_ENCRYPTION);
2872 subreq = smb1cli_trans_send(state, ev, cli->conn,
2880 NULL, /* pipe_name */
2886 in.data, in.length, CLI_BUFFER_SIZE);
2887 if (tevent_req_nomem(subreq, req)) {
2888 return tevent_req_post(req, ev);
2890 tevent_req_set_callback(subreq,
2891 cli_smb1_setup_encryption_blob_done,
2897 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq)
2899 struct tevent_req *req =
2900 tevent_req_callback_data(subreq,
2902 struct cli_smb1_setup_encryption_blob_state *state =
2903 tevent_req_data(req,
2904 struct cli_smb1_setup_encryption_blob_state);
2905 uint8_t *rparam=NULL, *rdata=NULL;
2906 uint32_t num_rparam, num_rdata;
2909 status = smb1cli_trans_recv(subreq, state,
2910 NULL, /* recv_flags */
2911 NULL, 0, NULL, /* rsetup */
2912 &rparam, 0, &num_rparam,
2913 &rdata, 0, &num_rdata);
2914 TALLOC_FREE(subreq);
2915 state->status = status;
2916 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2917 status = NT_STATUS_OK;
2919 if (tevent_req_nterror(req, status)) {
2923 if (num_rparam == 2) {
2924 state->enc_ctx_id = SVAL(rparam, 0);
2926 TALLOC_FREE(rparam);
2928 state->out = data_blob_const(rdata, num_rdata);
2930 tevent_req_done(req);
2933 static NTSTATUS cli_smb1_setup_encryption_blob_recv(struct tevent_req *req,
2934 TALLOC_CTX *mem_ctx,
2936 uint16_t *enc_ctx_id)
2938 struct cli_smb1_setup_encryption_blob_state *state =
2939 tevent_req_data(req,
2940 struct cli_smb1_setup_encryption_blob_state);
2943 if (tevent_req_is_nterror(req, &status)) {
2944 tevent_req_received(req);
2948 status = state->status;
2951 talloc_steal(mem_ctx, out->data);
2953 *enc_ctx_id = state->enc_ctx_id;
2955 tevent_req_received(req);
2959 struct cli_smb1_setup_encryption_state {
2960 struct tevent_context *ev;
2961 struct cli_state *cli;
2962 struct smb_trans_enc_state *es;
2969 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req);
2970 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq);
2971 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req);
2972 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq);
2973 static void cli_smb1_setup_encryption_ready(struct tevent_req *req);
2975 static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
2976 struct tevent_context *ev,
2977 struct cli_state *cli,
2978 struct cli_credentials *creds)
2980 struct tevent_req *req = NULL;
2981 struct cli_smb1_setup_encryption_state *state = NULL;
2982 struct auth_generic_state *ags = NULL;
2983 const DATA_BLOB *b = NULL;
2984 bool auth_requested = false;
2985 const char *target_service = NULL;
2986 const char *target_hostname = NULL;
2989 req = tevent_req_create(mem_ctx, &state,
2990 struct cli_smb1_setup_encryption_state);
2997 auth_requested = cli_credentials_authentication_requested(creds);
2998 if (!auth_requested) {
2999 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3000 return tevent_req_post(req, ev);
3003 target_service = "cifs";
3004 target_hostname = smbXcli_conn_remote_name(cli->conn);
3006 status = cli_session_creds_prepare_krb5(cli, creds);
3007 if (tevent_req_nterror(req, status)) {
3008 return tevent_req_post(req, ev);
3011 state->es = talloc_zero(state, struct smb_trans_enc_state);
3012 if (tevent_req_nomem(state->es, req)) {
3013 return tevent_req_post(req, ev);
3016 status = auth_generic_client_prepare(state->es, &ags);
3017 if (tevent_req_nterror(req, status)) {
3018 return tevent_req_post(req, ev);
3021 gensec_want_feature(ags->gensec_security,
3022 GENSEC_FEATURE_SIGN);
3023 gensec_want_feature(ags->gensec_security,
3024 GENSEC_FEATURE_SEAL);
3026 status = auth_generic_set_creds(ags, creds);
3027 if (tevent_req_nterror(req, status)) {
3028 return tevent_req_post(req, ev);
3031 if (target_service != NULL) {
3032 status = gensec_set_target_service(ags->gensec_security,
3034 if (tevent_req_nterror(req, status)) {
3035 return tevent_req_post(req, ev);
3039 if (target_hostname != NULL) {
3040 status = gensec_set_target_hostname(ags->gensec_security,
3042 if (tevent_req_nterror(req, status)) {
3043 return tevent_req_post(req, ev);
3047 gensec_set_max_update_size(ags->gensec_security,
3050 b = smbXcli_conn_server_gss_blob(state->cli->conn);
3052 state->blob_in = *b;
3055 status = auth_generic_client_start(ags, GENSEC_OID_SPNEGO);
3056 if (tevent_req_nterror(req, status)) {
3057 return tevent_req_post(req, ev);
3061 * We only need the gensec_security part from here.
3063 state->es->gensec_security = talloc_move(state->es,
3064 &ags->gensec_security);
3067 cli_smb1_setup_encryption_local_next(req);
3068 if (!tevent_req_is_in_progress(req)) {
3069 return tevent_req_post(req, ev);
3075 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req)
3077 struct cli_smb1_setup_encryption_state *state =
3078 tevent_req_data(req,
3079 struct cli_smb1_setup_encryption_state);
3080 struct tevent_req *subreq = NULL;
3082 if (state->local_ready) {
3083 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3087 subreq = gensec_update_send(state, state->ev,
3088 state->es->gensec_security,
3090 if (tevent_req_nomem(subreq, req)) {
3093 tevent_req_set_callback(subreq, cli_smb1_setup_encryption_local_done, req);
3096 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq)
3098 struct tevent_req *req =
3099 tevent_req_callback_data(subreq,
3101 struct cli_smb1_setup_encryption_state *state =
3102 tevent_req_data(req,
3103 struct cli_smb1_setup_encryption_state);
3106 status = gensec_update_recv(subreq, state, &state->blob_out);
3107 TALLOC_FREE(subreq);
3108 state->blob_in = data_blob_null;
3109 if (!NT_STATUS_IS_OK(status) &&
3110 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3112 tevent_req_nterror(req, status);
3116 if (NT_STATUS_IS_OK(status)) {
3117 state->local_ready = true;
3121 * We always get NT_STATUS_OK from the server even if it is not ready.
3122 * So guess the server is ready when we are ready and already sent
3123 * our last blob to the server.
3125 if (state->local_ready && state->blob_out.length == 0) {
3126 state->remote_ready = true;
3129 if (state->local_ready && state->remote_ready) {
3130 cli_smb1_setup_encryption_ready(req);
3134 cli_smb1_setup_encryption_remote_next(req);
3137 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req)
3139 struct cli_smb1_setup_encryption_state *state =
3140 tevent_req_data(req,
3141 struct cli_smb1_setup_encryption_state);
3142 struct tevent_req *subreq = NULL;
3144 if (state->remote_ready) {
3145 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3149 subreq = cli_smb1_setup_encryption_blob_send(state, state->ev,
3150 state->cli, state->blob_out);
3151 if (tevent_req_nomem(subreq, req)) {
3154 tevent_req_set_callback(subreq,
3155 cli_smb1_setup_encryption_remote_done,
3159 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq)
3161 struct tevent_req *req =
3162 tevent_req_callback_data(subreq,
3164 struct cli_smb1_setup_encryption_state *state =
3165 tevent_req_data(req,
3166 struct cli_smb1_setup_encryption_state);
3169 status = cli_smb1_setup_encryption_blob_recv(subreq, state,
3171 &state->es->enc_ctx_num);
3172 TALLOC_FREE(subreq);
3173 data_blob_free(&state->blob_out);
3174 if (!NT_STATUS_IS_OK(status) &&
3175 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3177 tevent_req_nterror(req, status);
3182 * We always get NT_STATUS_OK even if the server is not ready.
3183 * So guess the server is ready when we are ready and sent
3184 * our last blob to the server.
3186 if (state->local_ready) {
3187 state->remote_ready = true;
3190 if (state->local_ready && state->remote_ready) {
3191 cli_smb1_setup_encryption_ready(req);
3195 cli_smb1_setup_encryption_local_next(req);
3198 static void cli_smb1_setup_encryption_ready(struct tevent_req *req)
3200 struct cli_smb1_setup_encryption_state *state =
3201 tevent_req_data(req,
3202 struct cli_smb1_setup_encryption_state);
3203 struct smb_trans_enc_state *es = NULL;
3205 if (state->blob_in.length != 0) {
3206 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3210 if (state->blob_out.length != 0) {
3211 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3215 es = talloc_move(state->cli->conn, &state->es);
3217 smb1cli_conn_set_encryption(state->cli->conn, es);
3220 tevent_req_done(req);
3223 static NTSTATUS cli_smb1_setup_encryption_recv(struct tevent_req *req)
3225 return tevent_req_simple_recv_ntstatus(req);
3228 NTSTATUS cli_smb1_setup_encryption(struct cli_state *cli,
3229 struct cli_credentials *creds)
3231 struct tevent_context *ev = NULL;
3232 struct tevent_req *req = NULL;
3233 NTSTATUS status = NT_STATUS_NO_MEMORY;
3235 ev = samba_tevent_context_init(talloc_tos());
3239 req = cli_smb1_setup_encryption_send(ev, ev, cli, creds);
3243 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3246 status = cli_smb1_setup_encryption_recv(req);
3253 establishes a connection right up to doing tconX, password specified.
3254 @param output_cli A fully initialised cli structure, non-null only on success
3255 @param dest_host The netbios name of the remote host
3256 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3257 @param port (optional) The destination port (0 for default)
3258 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3259 @param service_type The 'type' of serivice.
3260 @param creds The used user credentials
3263 struct cli_full_connection_creds_state {
3264 struct tevent_context *ev;
3265 const char *service;
3266 const char *service_type;
3267 struct cli_credentials *creds;
3269 struct cli_state *cli;
3272 static int cli_full_connection_creds_state_destructor(
3273 struct cli_full_connection_creds_state *s)
3275 if (s->cli != NULL) {
3276 cli_shutdown(s->cli);
3282 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq);
3283 static void cli_full_connection_creds_sess_start(struct tevent_req *req);
3284 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq);
3285 static void cli_full_connection_creds_tcon_start(struct tevent_req *req);
3286 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq);
3288 struct tevent_req *cli_full_connection_creds_send(
3289 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3290 const char *my_name, const char *dest_host,
3291 const struct sockaddr_storage *dest_ss, int port,
3292 const char *service, const char *service_type,
3293 struct cli_credentials *creds,
3294 int flags, int signing_state)
3296 struct tevent_req *req, *subreq;
3297 struct cli_full_connection_creds_state *state;
3298 enum credentials_use_kerberos krb5_state;
3299 uint32_t gensec_features = 0;
3301 req = tevent_req_create(mem_ctx, &state,
3302 struct cli_full_connection_creds_state);
3306 talloc_set_destructor(state, cli_full_connection_creds_state_destructor);
3308 flags &= ~CLI_FULL_CONNECTION_USE_KERBEROS;
3309 flags &= ~CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
3310 flags &= ~CLI_FULL_CONNECTION_USE_CCACHE;
3311 flags &= ~CLI_FULL_CONNECTION_USE_NT_HASH;
3313 krb5_state = cli_credentials_get_kerberos_state(creds);
3314 switch (krb5_state) {
3315 case CRED_MUST_USE_KERBEROS:
3316 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3317 flags &= ~CLI_FULL_CONNECTION_DONT_SPNEGO;
3319 case CRED_AUTO_USE_KERBEROS:
3320 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3321 flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
3323 case CRED_DONT_USE_KERBEROS:
3327 gensec_features = cli_credentials_get_gensec_features(creds);
3328 if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
3329 flags |= CLI_FULL_CONNECTION_USE_CCACHE;
3333 state->service = service;
3334 state->service_type = service_type;
3335 state->creds = creds;
3336 state->flags = flags;
3338 subreq = cli_start_connection_send(
3339 state, ev, my_name, dest_host, dest_ss, port,
3340 signing_state, flags);
3341 if (tevent_req_nomem(subreq, req)) {
3342 return tevent_req_post(req, ev);
3344 tevent_req_set_callback(subreq,
3345 cli_full_connection_creds_conn_done,
3350 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq)
3352 struct tevent_req *req = tevent_req_callback_data(
3353 subreq, struct tevent_req);
3354 struct cli_full_connection_creds_state *state = tevent_req_data(
3355 req, struct cli_full_connection_creds_state);
3358 status = cli_start_connection_recv(subreq, &state->cli);
3359 TALLOC_FREE(subreq);
3360 if (tevent_req_nterror(req, status)) {
3364 cli_full_connection_creds_sess_start(req);
3367 static void cli_full_connection_creds_sess_start(struct tevent_req *req)
3369 struct cli_full_connection_creds_state *state = tevent_req_data(
3370 req, struct cli_full_connection_creds_state);
3371 struct tevent_req *subreq = NULL;
3373 subreq = cli_session_setup_creds_send(
3374 state, state->ev, state->cli, state->creds);
3375 if (tevent_req_nomem(subreq, req)) {
3378 tevent_req_set_callback(subreq,
3379 cli_full_connection_creds_sess_done,
3383 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq)
3385 struct tevent_req *req = tevent_req_callback_data(
3386 subreq, struct tevent_req);
3387 struct cli_full_connection_creds_state *state = tevent_req_data(
3388 req, struct cli_full_connection_creds_state);
3391 status = cli_session_setup_creds_recv(subreq);
3392 TALLOC_FREE(subreq);
3394 if (!NT_STATUS_IS_OK(status) &&
3395 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3397 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3399 state->creds = cli_credentials_init_anon(state);
3400 if (tevent_req_nomem(state->creds, req)) {
3404 cli_full_connection_creds_sess_start(req);
3408 if (tevent_req_nterror(req, status)) {
3412 cli_full_connection_creds_tcon_start(req);
3415 static void cli_full_connection_creds_tcon_start(struct tevent_req *req)
3417 struct cli_full_connection_creds_state *state = tevent_req_data(
3418 req, struct cli_full_connection_creds_state);
3419 struct tevent_req *subreq = NULL;
3420 const char *password = NULL;
3422 if (state->service == NULL) {
3423 tevent_req_done(req);
3427 password = cli_credentials_get_password(state->creds);
3429 subreq = cli_tree_connect_send(state, state->ev,
3432 state->service_type,
3434 if (tevent_req_nomem(subreq, req)) {
3437 tevent_req_set_callback(subreq,
3438 cli_full_connection_creds_tcon_done,
3442 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq)
3444 struct tevent_req *req = tevent_req_callback_data(
3445 subreq, struct tevent_req);
3448 status = cli_tree_connect_recv(subreq);
3449 TALLOC_FREE(subreq);
3450 if (tevent_req_nterror(req, status)) {
3454 tevent_req_done(req);
3457 NTSTATUS cli_full_connection_creds_recv(struct tevent_req *req,
3458 struct cli_state **output_cli)
3460 struct cli_full_connection_creds_state *state = tevent_req_data(
3461 req, struct cli_full_connection_creds_state);
3464 if (tevent_req_is_nterror(req, &status)) {
3467 *output_cli = state->cli;
3468 talloc_set_destructor(state, NULL);
3469 return NT_STATUS_OK;
3472 NTSTATUS cli_full_connection_creds(struct cli_state **output_cli,
3473 const char *my_name,
3474 const char *dest_host,
3475 const struct sockaddr_storage *dest_ss, int port,
3476 const char *service, const char *service_type,
3477 struct cli_credentials *creds,
3481 struct tevent_context *ev;
3482 struct tevent_req *req;
3483 NTSTATUS status = NT_STATUS_NO_MEMORY;
3485 ev = samba_tevent_context_init(talloc_tos());
3489 req = cli_full_connection_creds_send(
3490 ev, ev, my_name, dest_host, dest_ss, port, service,
3491 service_type, creds, flags, signing_state);
3495 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3498 status = cli_full_connection_creds_recv(req, output_cli);
3504 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3505 const char *my_name,
3506 const char *dest_host,
3507 const struct sockaddr_storage *dest_ss, int port,
3508 const char *service, const char *service_type,
3509 const char *user, const char *domain,
3510 const char *password, int flags,
3513 TALLOC_CTX *frame = talloc_stackframe();
3515 bool use_kerberos = false;
3516 bool fallback_after_kerberos = false;
3517 bool use_ccache = false;
3518 bool pw_nt_hash = false;
3519 struct cli_credentials *creds = NULL;
3521 if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) {
3522 use_kerberos = true;
3525 if (flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) {
3526 fallback_after_kerberos = true;
3529 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
3533 if (flags & CLI_FULL_CONNECTION_USE_NT_HASH) {
3537 creds = cli_session_creds_init(frame,
3540 NULL, /* realm (use default) */
3543 fallback_after_kerberos,
3546 if (creds == NULL) {
3548 return NT_STATUS_NO_MEMORY;
3551 status = cli_full_connection_creds(output_cli, my_name,
3552 dest_host, dest_ss, port,
3553 service, service_type,
3554 creds, flags, signing_state);
3555 if (!NT_STATUS_IS_OK(status)) {
3561 return NT_STATUS_OK;
3564 /****************************************************************************
3565 Send an old style tcon.
3566 ****************************************************************************/
3567 struct cli_raw_tcon_state {
3571 static void cli_raw_tcon_done(struct tevent_req *subreq);
3573 static struct tevent_req *cli_raw_tcon_send(
3574 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3575 const char *service, const char *pass, const char *dev)
3577 struct tevent_req *req, *subreq;
3578 struct cli_raw_tcon_state *state;
3581 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3586 if (!lp_client_plaintext_auth() && (*pass)) {
3587 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3588 " or 'client ntlmv2 auth = yes'\n"));
3589 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3590 return tevent_req_post(req, ev);
3593 bytes = talloc_array(state, uint8_t, 0);
3594 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3595 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3596 service, strlen(service)+1, NULL);
3597 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3598 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3599 pass, strlen(pass)+1, NULL);
3600 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3601 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3602 dev, strlen(dev)+1, NULL);
3604 if (tevent_req_nomem(bytes, req)) {
3605 return tevent_req_post(req, ev);
3608 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3609 talloc_get_size(bytes), bytes);
3610 if (tevent_req_nomem(subreq, req)) {
3611 return tevent_req_post(req, ev);
3613 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3617 static void cli_raw_tcon_done(struct tevent_req *subreq)
3619 struct tevent_req *req = tevent_req_callback_data(
3620 subreq, struct tevent_req);
3621 struct cli_raw_tcon_state *state = tevent_req_data(
3622 req, struct cli_raw_tcon_state);
3625 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3627 TALLOC_FREE(subreq);
3628 if (tevent_req_nterror(req, status)) {
3631 tevent_req_done(req);
3634 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3635 uint16_t *max_xmit, uint16_t *tid)
3637 struct cli_raw_tcon_state *state = tevent_req_data(
3638 req, struct cli_raw_tcon_state);
3641 if (tevent_req_is_nterror(req, &status)) {
3644 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3645 *tid = SVAL(state->ret_vwv + 1, 0);
3646 return NT_STATUS_OK;
3649 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3650 const char *service, const char *pass, const char *dev,
3651 uint16_t *max_xmit, uint16_t *tid)
3653 struct tevent_context *ev;
3654 struct tevent_req *req;
3655 NTSTATUS status = NT_STATUS_NO_MEMORY;
3657 ev = samba_tevent_context_init(talloc_tos());
3661 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3665 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3668 status = cli_raw_tcon_recv(req, max_xmit, tid);
3674 /* Return a cli_state pointing at the IPC$ share for the given server */
3676 struct cli_state *get_ipc_connect(char *server,
3677 struct sockaddr_storage *server_ss,
3678 const struct user_auth_info *user_info)
3680 struct cli_state *cli;
3682 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3684 if (get_cmdline_auth_info_use_kerberos(user_info)) {
3685 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3688 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3689 get_cmdline_auth_info_username(user_info),
3691 get_cmdline_auth_info_password(user_info),
3693 SMB_SIGNING_DEFAULT);
3695 if (NT_STATUS_IS_OK(nt_status)) {
3697 } else if (is_ipaddress(server)) {
3698 /* windows 9* needs a correct NMB name for connections */
3699 fstring remote_name;
3701 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3702 cli = get_ipc_connect(remote_name, server_ss, user_info);
3711 * Given the IP address of a master browser on the network, return its
3712 * workgroup and connect to it.
3714 * This function is provided to allow additional processing beyond what
3715 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3716 * browsers and obtain each master browsers' list of domains (in case the
3717 * first master browser is recently on the network and has not yet
3718 * synchronized with other master browsers and therefore does not yet have the
3719 * entire network browse list)
3722 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3723 struct sockaddr_storage *mb_ip,
3724 const struct user_auth_info *user_info,
3725 char **pp_workgroup_out)
3727 char addr[INET6_ADDRSTRLEN];
3729 struct cli_state *cli;
3730 struct sockaddr_storage server_ss;
3732 *pp_workgroup_out = NULL;
3734 print_sockaddr(addr, sizeof(addr), mb_ip);
3735 DEBUG(99, ("Looking up name of master browser %s\n",
3739 * Do a name status query to find out the name of the master browser.
3740 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3741 * master browser will not respond to a wildcard query (or, at least,
3742 * an NT4 server acting as the domain master browser will not).
3744 * We might be able to use ONLY the query on MSBROWSE, but that's not
3745 * yet been tested with all Windows versions, so until it is, leave
3746 * the original wildcard query as the first choice and fall back to
3747 * MSBROWSE if the wildcard query fails.
3749 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3750 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3752 DEBUG(99, ("Could not retrieve name status for %s\n",
3757 if (!find_master_ip(name, &server_ss)) {
3758 DEBUG(99, ("Could not find master ip for %s\n", name));
3762 *pp_workgroup_out = talloc_strdup(ctx, name);
3764 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3766 print_sockaddr(addr, sizeof(addr), &server_ss);
3767 cli = get_ipc_connect(addr, &server_ss, user_info);
3773 * Return the IP address and workgroup of a master browser on the network, and
3777 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3778 const struct user_auth_info *user_info,
3779 char **pp_workgroup_out)
3781 struct sockaddr_storage *ip_list;
3782 struct cli_state *cli;
3786 *pp_workgroup_out = NULL;
3788 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3790 /* Go looking for workgroups by broadcasting on the local network */
3792 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3794 if (!NT_STATUS_IS_OK(status)) {
3795 DEBUG(99, ("No master browsers responded: %s\n",
3796 nt_errstr(status)));
3800 for (i = 0; i < count; i++) {
3801 char addr[INET6_ADDRSTRLEN];
3802 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3803 DEBUG(99, ("Found master browser %s\n", addr));
3805 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3806 user_info, pp_workgroup_out);