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,
1074 * we need to continue as anonymous from this point,
1075 * as we can't get a session key.
1077 * Note that smbXcli_session_is_guest()
1078 * always returns false if we require signing.
1080 state->blob_in = data_blob_null;
1081 state->local_ready = true;
1082 state->is_anonymous = true;
1085 state->remote_ready = true;
1088 if (state->local_ready && state->remote_ready) {
1089 cli_session_setup_gensec_ready(req);
1093 cli_session_setup_gensec_local_next(req);
1096 static void cli_session_setup_gensec_ready(struct tevent_req *req)
1098 struct cli_session_setup_gensec_state *state =
1099 tevent_req_data(req,
1100 struct cli_session_setup_gensec_state);
1101 const char *server_domain = NULL;
1104 if (state->blob_in.length != 0) {
1105 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1109 if (state->blob_out.length != 0) {
1110 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1115 * gensec_ntlmssp_server_domain() returns NULL
1116 * if NTLMSSP is not used.
1118 * We can remove this later
1119 * and leave the server domain empty for SMB2 and above
1120 * in future releases.
1122 server_domain = gensec_ntlmssp_server_domain(
1123 state->auth_generic->gensec_security);
1125 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
1126 TALLOC_FREE(state->cli->server_domain);
1127 state->cli->server_domain = talloc_strdup(state->cli,
1129 if (state->cli->server_domain == NULL) {
1130 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1135 if (state->is_anonymous) {
1137 * Windows server does not set the
1138 * SMB2_SESSION_FLAG_IS_NULL flag.
1140 * This fix makes sure we do not try
1141 * to verify a signature on the final
1142 * session setup response.
1144 tevent_req_done(req);
1148 status = gensec_session_key(state->auth_generic->gensec_security,
1149 state, &state->session_key);
1150 if (tevent_req_nterror(req, status)) {
1154 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1155 struct smbXcli_session *session = state->cli->smb2.session;
1157 status = smb2cli_session_set_session_key(session,
1160 if (tevent_req_nterror(req, status)) {
1164 struct smbXcli_session *session = state->cli->smb1.session;
1167 status = smb1cli_session_set_session_key(session,
1168 state->session_key);
1169 if (tevent_req_nterror(req, status)) {
1173 active = smb1cli_conn_activate_signing(state->cli->conn,
1179 ok = smb1cli_conn_check_signing(state->cli->conn,
1182 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1188 tevent_req_done(req);
1191 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1193 struct cli_session_setup_gensec_state *state =
1194 tevent_req_data(req,
1195 struct cli_session_setup_gensec_state);
1198 if (tevent_req_is_nterror(req, &status)) {
1199 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1202 return NT_STATUS_OK;
1205 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1206 const char *principal)
1210 account = talloc_strdup(mem_ctx, principal);
1211 if (account == NULL) {
1214 p = strchr_m(account, '@');
1221 /****************************************************************************
1222 Do a spnego encrypted session setup.
1224 user_domain: The shortname of the domain the user/machine is a member of.
1225 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1226 ****************************************************************************/
1228 struct cli_session_setup_spnego_state {
1232 static void cli_session_setup_spnego_done(struct tevent_req *subreq);
1234 static struct tevent_req *cli_session_setup_spnego_send(
1235 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1236 struct cli_credentials *creds)
1238 struct tevent_req *req, *subreq;
1239 struct cli_session_setup_spnego_state *state;
1240 const char *target_service = NULL;
1241 const char *target_hostname = NULL;
1244 req = tevent_req_create(mem_ctx, &state,
1245 struct cli_session_setup_spnego_state);
1250 target_service = "cifs";
1251 target_hostname = smbXcli_conn_remote_name(cli->conn);
1253 status = cli_session_creds_prepare_krb5(cli, creds);
1254 if (tevent_req_nterror(req, status)) {
1255 return tevent_req_post(req, ev);;
1258 subreq = cli_session_setup_gensec_send(state, ev, cli, creds,
1259 target_service, target_hostname);
1260 if (tevent_req_nomem(subreq, req)) {
1261 return tevent_req_post(req, ev);
1263 tevent_req_set_callback(
1264 subreq, cli_session_setup_spnego_done, req);
1268 static void cli_session_setup_spnego_done(struct tevent_req *subreq)
1270 struct tevent_req *req = tevent_req_callback_data(
1271 subreq, struct tevent_req);
1274 status = cli_session_setup_gensec_recv(subreq);
1275 TALLOC_FREE(subreq);
1276 if (tevent_req_nterror(req, status)) {
1280 tevent_req_done(req);
1283 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1285 struct cli_session_setup_spnego_state *state = tevent_req_data(
1286 req, struct cli_session_setup_spnego_state);
1289 if (tevent_req_is_nterror(req, &status)) {
1290 state->result = ADS_ERROR_NT(status);
1293 return state->result;
1296 struct cli_session_setup_creds_state {
1297 struct cli_state *cli;
1298 DATA_BLOB apassword_blob;
1299 DATA_BLOB upassword_blob;
1300 DATA_BLOB lm_session_key;
1301 DATA_BLOB session_key;
1302 char *out_native_os;
1303 char *out_native_lm;
1304 char *out_primary_domain;
1307 static void cli_session_setup_creds_cleanup(struct tevent_req *req,
1308 enum tevent_req_state req_state)
1310 struct cli_session_setup_creds_state *state = tevent_req_data(
1311 req, struct cli_session_setup_creds_state);
1313 if (req_state != TEVENT_REQ_RECEIVED) {
1318 * We only call data_blob_clear() as
1319 * some of the blobs point to the same memory.
1321 * We let the talloc hierachy free the memory.
1323 data_blob_clear(&state->apassword_blob);
1324 data_blob_clear(&state->upassword_blob);
1325 data_blob_clear(&state->lm_session_key);
1326 data_blob_clear(&state->session_key);
1327 ZERO_STRUCTP(state);
1330 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq);
1331 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq);
1332 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq);
1334 /****************************************************************************
1335 Send a session setup. The username and workgroup is in UNIX character
1336 format and must be converted to DOS codepage format before sending. If the
1337 password is in plaintext, the same should be done.
1338 ****************************************************************************/
1340 struct tevent_req *cli_session_setup_creds_send(TALLOC_CTX *mem_ctx,
1341 struct tevent_context *ev,
1342 struct cli_state *cli,
1343 struct cli_credentials *creds)
1345 struct tevent_req *req, *subreq;
1346 struct cli_session_setup_creds_state *state;
1347 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1348 bool use_spnego = false;
1350 enum credentials_use_kerberos krb5_state;
1351 uint32_t gensec_features;
1352 const char *username = "";
1353 const char *domain = "";
1354 DATA_BLOB target_info = data_blob_null;
1355 DATA_BLOB challenge = data_blob_null;
1356 uint16_t in_buf_size = 0;
1357 uint16_t in_mpx_max = 0;
1358 uint16_t in_vc_num = 0;
1359 uint32_t in_sess_key = 0;
1360 const char *in_native_os = NULL;
1361 const char *in_native_lm = NULL;
1364 req = tevent_req_create(mem_ctx, &state,
1365 struct cli_session_setup_creds_state);
1371 tevent_req_set_cleanup_fn(req, cli_session_setup_creds_cleanup);
1373 krb5_state = cli_credentials_get_kerberos_state(creds);
1374 gensec_features = cli_credentials_get_gensec_features(creds);
1376 switch (krb5_state) {
1377 case CRED_MUST_USE_KERBEROS:
1378 cli->use_kerberos = true;
1379 cli->fallback_after_kerberos = false;
1381 case CRED_AUTO_USE_KERBEROS:
1382 cli->use_kerberos = true;
1383 cli->fallback_after_kerberos = true;
1385 case CRED_DONT_USE_KERBEROS:
1386 cli->use_kerberos = false;
1387 cli->fallback_after_kerberos = false;
1391 if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
1392 cli->use_ccache = true;
1394 cli->use_ccache = false;
1398 * Now work out what sort of session setup we are going to
1399 * do. I have split this into separate functions to make the flow a bit
1400 * easier to understand (tridge).
1402 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
1404 } else if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1406 } else if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
1408 * if the server supports extended security then use SPNEGO
1409 * even for anonymous connections.
1417 subreq = cli_session_setup_spnego_send(
1418 state, ev, cli, creds);
1419 if (tevent_req_nomem(subreq, req)) {
1420 return tevent_req_post(req, ev);
1422 tevent_req_set_callback(subreq, cli_session_setup_creds_done_spnego,
1427 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1429 * SessionSetupAndX was introduced by LANMAN 1.0. So we skip
1430 * this step against older servers.
1432 tevent_req_done(req);
1433 return tevent_req_post(req, ev);
1436 if (cli_credentials_is_anonymous(creds)) {
1438 * Do an anonymous session setup
1440 goto non_spnego_creds_done;
1443 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
1445 * Do an anonymous session setup,
1446 * the password is passed via the tree connect.
1448 goto non_spnego_creds_done;
1451 cli_credentials_get_ntlm_username_domain(creds, state,
1454 if (tevent_req_nomem(username, req)) {
1455 return tevent_req_post(req, ev);
1457 if (tevent_req_nomem(domain, req)) {
1458 return tevent_req_post(req, ev);
1461 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1462 bool use_unicode = smbXcli_conn_use_unicode(cli->conn);
1463 uint8_t *bytes = NULL;
1464 size_t bytes_len = 0;
1465 const char *pw = cli_credentials_get_password(creds);
1471 pw_len = strlen(pw) + 1;
1473 if (!lp_client_plaintext_auth()) {
1474 DEBUG(1, ("Server requested PLAINTEXT password but "
1475 "'client plaintext auth = no'\n"));
1476 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1477 return tevent_req_post(req, ev);
1480 bytes = talloc_array(state, uint8_t, 0);
1481 bytes = trans2_bytes_push_str(bytes, use_unicode,
1482 pw, pw_len, &bytes_len);
1483 if (tevent_req_nomem(bytes, req)) {
1484 return tevent_req_post(req, ev);
1489 * CAP_UNICODE, can only be negotiated by NT1.
1491 state->upassword_blob = data_blob_const(bytes,
1494 state->apassword_blob = data_blob_const(bytes,
1498 goto non_spnego_creds_done;
1501 challenge = data_blob_const(smb1cli_conn_server_challenge(cli->conn), 8);
1503 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1504 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
1506 * Don't send an NTLMv2 response without NTLMSSP if we
1507 * want to use spnego support.
1509 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
1510 " but 'client use spnego = yes'"
1511 " and 'client ntlmv2 auth = yes' is set\n"));
1512 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1513 return tevent_req_post(req, ev);
1516 if (lp_client_ntlmv2_auth()) {
1517 flags |= CLI_CRED_NTLMv2_AUTH;
1520 * note that the 'domain' here is a best
1521 * guess - we don't know the server's domain
1522 * at this point. Windows clients also don't
1525 target_info = NTLMv2_generate_names_blob(state,
1528 if (tevent_req_nomem(target_info.data, req)) {
1529 return tevent_req_post(req, ev);
1532 flags |= CLI_CRED_NTLM_AUTH;
1533 if (lp_client_lanman_auth()) {
1534 flags |= CLI_CRED_LANMAN_AUTH;
1538 if (!lp_client_lanman_auth()) {
1539 DEBUG(1, ("Server requested user level LM password but "
1540 "'client lanman auth = no' is set.\n"));
1541 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1542 return tevent_req_post(req, ev);
1545 flags |= CLI_CRED_LANMAN_AUTH;
1548 status = cli_credentials_get_ntlm_response(creds, state, &flags,
1551 &state->apassword_blob,
1552 &state->upassword_blob,
1553 &state->lm_session_key,
1554 &state->session_key);
1555 if (tevent_req_nterror(req, status)) {
1556 return tevent_req_post(req, ev);
1559 non_spnego_creds_done:
1561 in_buf_size = CLI_BUFFER_SIZE;
1562 in_mpx_max = smbXcli_conn_max_requests(cli->conn);
1563 in_vc_num = cli_state_get_vc_num(cli);
1564 in_sess_key = smb1cli_conn_server_session_key(cli->conn);
1565 in_native_os = "Unix";
1566 in_native_lm = "Samba";
1568 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1569 uint32_t in_capabilities = 0;
1571 in_capabilities = cli_session_setup_capabilities(cli, 0);
1574 * For now we keep the same values as before,
1575 * we may remove these in a separate commit later.
1579 subreq = smb1cli_session_setup_nt1_send(state, ev,
1590 state->apassword_blob,
1591 state->upassword_blob,
1595 if (tevent_req_nomem(subreq, req)) {
1596 return tevent_req_post(req, ev);
1598 tevent_req_set_callback(subreq, cli_session_setup_creds_done_nt1,
1604 * For now we keep the same values as before,
1605 * we may remove these in a separate commit later.
1610 subreq = smb1cli_session_setup_lm21_send(state, ev,
1621 state->apassword_blob,
1624 if (tevent_req_nomem(subreq, req)) {
1625 return tevent_req_post(req, ev);
1627 tevent_req_set_callback(subreq, cli_session_setup_creds_done_lm21,
1632 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq)
1634 struct tevent_req *req = tevent_req_callback_data(
1635 subreq, struct tevent_req);
1638 status = cli_session_setup_spnego_recv(subreq);
1639 TALLOC_FREE(subreq);
1640 if (!ADS_ERR_OK(status)) {
1641 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1642 tevent_req_nterror(req, ads_ntstatus(status));
1645 tevent_req_done(req);
1648 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq)
1650 struct tevent_req *req = tevent_req_callback_data(
1651 subreq, struct tevent_req);
1652 struct cli_session_setup_creds_state *state = tevent_req_data(
1653 req, struct cli_session_setup_creds_state);
1654 struct cli_state *cli = state->cli;
1656 struct iovec *recv_iov = NULL;
1657 const uint8_t *inbuf = NULL;
1660 status = smb1cli_session_setup_nt1_recv(subreq, state,
1663 &state->out_native_os,
1664 &state->out_native_lm,
1665 &state->out_primary_domain);
1666 TALLOC_FREE(subreq);
1667 if (!NT_STATUS_IS_OK(status)) {
1668 DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
1669 tevent_req_nterror(req, status);
1673 if (cli->server_os == NULL) {
1674 cli->server_os = talloc_move(cli, &state->out_native_os);
1676 if (cli->server_type == NULL) {
1677 cli->server_type = talloc_move(cli, &state->out_native_lm);
1679 if (cli->server_domain == NULL) {
1680 cli->server_domain = talloc_move(cli, &state->out_primary_domain);
1683 ok = smb1cli_conn_activate_signing(cli->conn,
1685 state->upassword_blob);
1687 ok = smb1cli_conn_check_signing(cli->conn, inbuf, 1);
1689 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1694 if (state->session_key.data) {
1695 struct smbXcli_session *session = cli->smb1.session;
1697 status = smb1cli_session_set_session_key(session,
1698 state->session_key);
1699 if (tevent_req_nterror(req, status)) {
1704 tevent_req_done(req);
1707 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq)
1709 struct tevent_req *req = tevent_req_callback_data(
1710 subreq, struct tevent_req);
1711 struct cli_session_setup_creds_state *state = tevent_req_data(
1712 req, struct cli_session_setup_creds_state);
1713 struct cli_state *cli = state->cli;
1716 status = smb1cli_session_setup_lm21_recv(subreq, state,
1717 &state->out_native_os,
1718 &state->out_native_lm);
1719 TALLOC_FREE(subreq);
1720 if (!NT_STATUS_IS_OK(status)) {
1721 DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
1722 tevent_req_nterror(req, status);
1726 if (cli->server_os == NULL) {
1727 cli->server_os = talloc_move(cli, &state->out_native_os);
1729 if (cli->server_type == NULL) {
1730 cli->server_type = talloc_move(cli, &state->out_native_lm);
1733 tevent_req_done(req);
1736 NTSTATUS cli_session_setup_creds_recv(struct tevent_req *req)
1738 return tevent_req_simple_recv_ntstatus(req);
1741 NTSTATUS cli_session_setup_creds(struct cli_state *cli,
1742 struct cli_credentials *creds)
1744 struct tevent_context *ev;
1745 struct tevent_req *req;
1746 NTSTATUS status = NT_STATUS_NO_MEMORY;
1748 if (smbXcli_conn_has_async_calls(cli->conn)) {
1749 return NT_STATUS_INVALID_PARAMETER;
1751 ev = samba_tevent_context_init(talloc_tos());
1755 req = cli_session_setup_creds_send(ev, ev, cli, creds);
1759 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1762 status = cli_session_setup_creds_recv(req);
1768 NTSTATUS cli_session_setup_anon(struct cli_state *cli)
1770 NTSTATUS status = NT_STATUS_NO_MEMORY;
1771 struct cli_credentials *creds = NULL;
1773 creds = cli_credentials_init_anon(cli);
1774 if (creds == NULL) {
1775 return NT_STATUS_NO_MEMORY;
1778 status = cli_session_setup_creds(cli, creds);
1780 if (!NT_STATUS_IS_OK(status)) {
1784 return NT_STATUS_OK;
1787 /****************************************************************************
1789 *****************************************************************************/
1791 struct cli_ulogoff_state {
1792 struct cli_state *cli;
1796 static void cli_ulogoff_done(struct tevent_req *subreq);
1798 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1799 struct tevent_context *ev,
1800 struct cli_state *cli)
1802 struct tevent_req *req, *subreq;
1803 struct cli_ulogoff_state *state;
1805 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1811 SCVAL(state->vwv+0, 0, 0xFF);
1812 SCVAL(state->vwv+1, 0, 0);
1813 SSVAL(state->vwv+2, 0, 0);
1815 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
1817 if (tevent_req_nomem(subreq, req)) {
1818 return tevent_req_post(req, ev);
1820 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1824 static void cli_ulogoff_done(struct tevent_req *subreq)
1826 struct tevent_req *req = tevent_req_callback_data(
1827 subreq, struct tevent_req);
1828 struct cli_ulogoff_state *state = tevent_req_data(
1829 req, struct cli_ulogoff_state);
1832 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1833 if (!NT_STATUS_IS_OK(status)) {
1834 tevent_req_nterror(req, status);
1837 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1838 tevent_req_done(req);
1841 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1843 return tevent_req_simple_recv_ntstatus(req);
1846 NTSTATUS cli_ulogoff(struct cli_state *cli)
1848 struct tevent_context *ev;
1849 struct tevent_req *req;
1850 NTSTATUS status = NT_STATUS_NO_MEMORY;
1852 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1853 status = smb2cli_logoff(cli->conn,
1856 if (!NT_STATUS_IS_OK(status)) {
1859 smb2cli_session_set_id_and_flags(cli->smb2.session,
1861 return NT_STATUS_OK;
1864 if (smbXcli_conn_has_async_calls(cli->conn)) {
1865 return NT_STATUS_INVALID_PARAMETER;
1867 ev = samba_tevent_context_init(talloc_tos());
1871 req = cli_ulogoff_send(ev, ev, cli);
1875 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1878 status = cli_ulogoff_recv(req);
1884 /****************************************************************************
1886 ****************************************************************************/
1888 struct cli_tcon_andx_state {
1889 struct cli_state *cli;
1894 static void cli_tcon_andx_done(struct tevent_req *subreq);
1896 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1897 struct tevent_context *ev,
1898 struct cli_state *cli,
1899 const char *share, const char *dev,
1900 const char *pass, int passlen,
1901 struct tevent_req **psmbreq)
1903 struct tevent_req *req, *subreq;
1904 struct cli_tcon_andx_state *state;
1909 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1910 uint16_t tcon_flags = 0;
1914 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1921 cli->share = talloc_strdup(cli, share);
1926 /* in user level security don't send a password now */
1927 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1930 } else if (pass == NULL) {
1931 DEBUG(1, ("Server not using user level security and no "
1932 "password supplied.\n"));
1936 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1937 *pass && passlen != 24) {
1938 if (!lp_client_lanman_auth()) {
1939 DEBUG(1, ("Server requested LANMAN password "
1940 "(share-level security) but "
1941 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
1946 * Non-encrypted passwords - convert to DOS codepage before
1949 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
1951 pass = (const char *)p24;
1953 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1954 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1958 if (!lp_client_plaintext_auth() && (*pass)) {
1959 DEBUG(1, ("Server requested PLAINTEXT "
1961 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
1966 * Non-encrypted passwords - convert to DOS codepage
1969 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
1970 if (tevent_req_nomem(tmp_pass, req)) {
1971 return tevent_req_post(req, ev);
1973 tmp_pass = trans2_bytes_push_str(tmp_pass,
1974 false, /* always DOS */
1978 if (tevent_req_nomem(tmp_pass, req)) {
1979 return tevent_req_post(req, ev);
1981 pass = (const char *)tmp_pass;
1982 passlen = talloc_get_size(tmp_pass);
1986 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
1987 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
1989 SCVAL(vwv+0, 0, 0xFF);
1992 SSVAL(vwv+2, 0, tcon_flags);
1993 SSVAL(vwv+3, 0, passlen);
1995 if (passlen && pass) {
1996 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
1998 bytes = talloc_array(state, uint8_t, 0);
2004 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2005 smbXcli_conn_remote_name(cli->conn), share);
2010 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2015 * Add the devicetype
2017 tmp = talloc_strdup_upper(talloc_tos(), dev);
2022 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2025 if (bytes == NULL) {
2030 state->bytes.iov_base = (void *)bytes;
2031 state->bytes.iov_len = talloc_get_size(bytes);
2033 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
2035 if (subreq == NULL) {
2039 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2044 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2045 return tevent_req_post(req, ev);
2048 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2049 struct tevent_context *ev,
2050 struct cli_state *cli,
2051 const char *share, const char *dev,
2052 const char *pass, int passlen)
2054 struct tevent_req *req, *subreq;
2057 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2062 if (subreq == NULL) {
2065 status = smb1cli_req_chain_submit(&subreq, 1);
2066 if (!NT_STATUS_IS_OK(status)) {
2067 tevent_req_nterror(req, status);
2068 return tevent_req_post(req, ev);
2073 static void cli_tcon_andx_done(struct tevent_req *subreq)
2075 struct tevent_req *req = tevent_req_callback_data(
2076 subreq, struct tevent_req);
2077 struct cli_tcon_andx_state *state = tevent_req_data(
2078 req, struct cli_tcon_andx_state);
2079 struct cli_state *cli = state->cli;
2087 uint16_t optional_support = 0;
2089 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2090 &num_bytes, &bytes);
2091 TALLOC_FREE(subreq);
2092 if (!NT_STATUS_IS_OK(status)) {
2093 tevent_req_nterror(req, status);
2097 inhdr = in + NBT_HDR_SIZE;
2100 if (clistr_pull_talloc(cli,
2101 (const char *)inhdr,
2102 SVAL(inhdr, HDR_FLG2),
2106 STR_TERMINATE|STR_ASCII) == -1) {
2107 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2111 cli->dev = talloc_strdup(cli, "");
2112 if (cli->dev == NULL) {
2113 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2118 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2119 /* almost certainly win95 - enable bug fixes */
2124 * Make sure that we have the optional support 16-bit field. WCT > 2.
2125 * Avoids issues when connecting to Win9x boxes sharing files
2128 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2129 optional_support = SVAL(vwv+2, 0);
2132 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2133 smb1cli_session_protect_session_key(cli->smb1.session);
2136 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2137 SVAL(inhdr, HDR_TID),
2139 0, /* maximal_access */
2140 0, /* guest_maximal_access */
2142 NULL); /* fs_type */
2144 tevent_req_done(req);
2147 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2149 return tevent_req_simple_recv_ntstatus(req);
2152 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2153 const char *dev, const char *pass, int passlen)
2155 TALLOC_CTX *frame = talloc_stackframe();
2156 struct tevent_context *ev;
2157 struct tevent_req *req;
2158 NTSTATUS status = NT_STATUS_NO_MEMORY;
2160 if (smbXcli_conn_has_async_calls(cli->conn)) {
2162 * Can't use sync call while an async call is in flight
2164 status = NT_STATUS_INVALID_PARAMETER;
2168 ev = samba_tevent_context_init(frame);
2173 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2178 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2182 status = cli_tcon_andx_recv(req);
2188 struct cli_tree_connect_state {
2189 struct cli_state *cli;
2192 static struct tevent_req *cli_raw_tcon_send(
2193 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2194 const char *service, const char *pass, const char *dev);
2195 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2196 uint16_t *max_xmit, uint16_t *tid);
2198 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2199 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2200 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2202 static struct tevent_req *cli_tree_connect_send(
2203 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2204 const char *share, const char *dev, const char *pass)
2206 struct tevent_req *req, *subreq;
2207 struct cli_tree_connect_state *state;
2213 passlen = strlen(pass) + 1;
2215 req = tevent_req_create(mem_ctx, &state,
2216 struct cli_tree_connect_state);
2222 cli->share = talloc_strdup(cli, share);
2223 if (tevent_req_nomem(cli->share, req)) {
2224 return tevent_req_post(req, ev);
2227 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2230 cli->smb2.tcon = smbXcli_tcon_create(cli);
2231 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2232 return tevent_req_post(req, ev);
2235 unc = talloc_asprintf(state, "\\\\%s\\%s",
2236 smbXcli_conn_remote_name(cli->conn),
2238 if (tevent_req_nomem(unc, req)) {
2239 return tevent_req_post(req, ev);
2242 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2243 cli->smb2.session, cli->smb2.tcon,
2246 if (tevent_req_nomem(subreq, req)) {
2247 return tevent_req_post(req, ev);
2249 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2254 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2255 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2257 if (tevent_req_nomem(subreq, req)) {
2258 return tevent_req_post(req, ev);
2260 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2265 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2266 if (tevent_req_nomem(subreq, req)) {
2267 return tevent_req_post(req, ev);
2269 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2274 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2276 tevent_req_simple_finish_ntstatus(
2277 subreq, smb2cli_tcon_recv(subreq));
2280 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2282 tevent_req_simple_finish_ntstatus(
2283 subreq, cli_tcon_andx_recv(subreq));
2286 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2288 struct tevent_req *req = tevent_req_callback_data(
2289 subreq, struct tevent_req);
2290 struct cli_tree_connect_state *state = tevent_req_data(
2291 req, struct cli_tree_connect_state);
2293 uint16_t max_xmit = 0;
2296 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2297 if (tevent_req_nterror(req, status)) {
2301 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2303 0, /* optional_support */
2304 0, /* maximal_access */
2305 0, /* guest_maximal_access */
2307 NULL); /* fs_type */
2309 tevent_req_done(req);
2312 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2314 return tevent_req_simple_recv_ntstatus(req);
2317 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2318 const char *dev, const char *pass)
2320 struct tevent_context *ev;
2321 struct tevent_req *req;
2322 NTSTATUS status = NT_STATUS_NO_MEMORY;
2324 if (smbXcli_conn_has_async_calls(cli->conn)) {
2325 return NT_STATUS_INVALID_PARAMETER;
2327 ev = samba_tevent_context_init(talloc_tos());
2331 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass);
2335 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2338 status = cli_tree_connect_recv(req);
2344 NTSTATUS cli_tree_connect_creds(struct cli_state *cli,
2345 const char *share, const char *dev,
2346 struct cli_credentials *creds)
2348 const char *pw = NULL;
2350 if (creds != NULL) {
2351 pw = cli_credentials_get_password(creds);
2354 return cli_tree_connect(cli, share, dev, pw);
2357 /****************************************************************************
2358 Send a tree disconnect.
2359 ****************************************************************************/
2361 struct cli_tdis_state {
2362 struct cli_state *cli;
2365 static void cli_tdis_done(struct tevent_req *subreq);
2367 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2368 struct tevent_context *ev,
2369 struct cli_state *cli)
2371 struct tevent_req *req, *subreq;
2372 struct cli_tdis_state *state;
2374 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2380 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2381 if (tevent_req_nomem(subreq, req)) {
2382 return tevent_req_post(req, ev);
2384 tevent_req_set_callback(subreq, cli_tdis_done, req);
2388 static void cli_tdis_done(struct tevent_req *subreq)
2390 struct tevent_req *req = tevent_req_callback_data(
2391 subreq, struct tevent_req);
2392 struct cli_tdis_state *state = tevent_req_data(
2393 req, struct cli_tdis_state);
2396 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2397 TALLOC_FREE(subreq);
2398 if (!NT_STATUS_IS_OK(status)) {
2399 tevent_req_nterror(req, status);
2402 cli_state_set_tid(state->cli, UINT16_MAX);
2403 tevent_req_done(req);
2406 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2408 return tevent_req_simple_recv_ntstatus(req);
2411 NTSTATUS cli_tdis(struct cli_state *cli)
2413 struct tevent_context *ev;
2414 struct tevent_req *req;
2415 NTSTATUS status = NT_STATUS_NO_MEMORY;
2417 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2418 return smb2cli_tdis(cli->conn,
2424 if (smbXcli_conn_has_async_calls(cli->conn)) {
2425 return NT_STATUS_INVALID_PARAMETER;
2427 ev = samba_tevent_context_init(talloc_tos());
2431 req = cli_tdis_send(ev, ev, cli);
2435 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2438 status = cli_tdis_recv(req);
2444 struct cli_connect_sock_state {
2445 const char **called_names;
2446 const char **calling_names;
2452 static void cli_connect_sock_done(struct tevent_req *subreq);
2455 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2459 static struct tevent_req *cli_connect_sock_send(
2460 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2461 const char *host, int name_type, const struct sockaddr_storage *pss,
2462 const char *myname, uint16_t port)
2464 struct tevent_req *req, *subreq;
2465 struct cli_connect_sock_state *state;
2467 struct sockaddr_storage *addrs;
2468 unsigned i, num_addrs;
2471 req = tevent_req_create(mem_ctx, &state,
2472 struct cli_connect_sock_state);
2477 prog = getenv("LIBSMB_PROG");
2479 state->fd = sock_exec(prog);
2480 if (state->fd == -1) {
2481 status = map_nt_error_from_unix(errno);
2482 tevent_req_nterror(req, status);
2485 tevent_req_done(req);
2487 return tevent_req_post(req, ev);
2490 if ((pss == NULL) || is_zero_addr(pss)) {
2493 * Here we cheat. resolve_name_list is not async at all. So
2494 * this call will only be really async if the name lookup has
2495 * been done externally.
2498 status = resolve_name_list(state, host, name_type,
2499 &addrs, &num_addrs);
2500 if (!NT_STATUS_IS_OK(status)) {
2501 tevent_req_nterror(req, status);
2502 return tevent_req_post(req, ev);
2505 addrs = talloc_array(state, struct sockaddr_storage, 1);
2506 if (tevent_req_nomem(addrs, req)) {
2507 return tevent_req_post(req, ev);
2513 state->called_names = talloc_array(state, const char *, num_addrs);
2514 if (tevent_req_nomem(state->called_names, req)) {
2515 return tevent_req_post(req, ev);
2517 state->called_types = talloc_array(state, int, num_addrs);
2518 if (tevent_req_nomem(state->called_types, req)) {
2519 return tevent_req_post(req, ev);
2521 state->calling_names = talloc_array(state, const char *, num_addrs);
2522 if (tevent_req_nomem(state->calling_names, req)) {
2523 return tevent_req_post(req, ev);
2525 for (i=0; i<num_addrs; i++) {
2526 state->called_names[i] = host;
2527 state->called_types[i] = name_type;
2528 state->calling_names[i] = myname;
2531 subreq = smbsock_any_connect_send(
2532 state, ev, addrs, state->called_names, state->called_types,
2533 state->calling_names, NULL, num_addrs, port);
2534 if (tevent_req_nomem(subreq, req)) {
2535 return tevent_req_post(req, ev);
2537 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2541 static void cli_connect_sock_done(struct tevent_req *subreq)
2543 struct tevent_req *req = tevent_req_callback_data(
2544 subreq, struct tevent_req);
2545 struct cli_connect_sock_state *state = tevent_req_data(
2546 req, struct cli_connect_sock_state);
2549 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2551 TALLOC_FREE(subreq);
2552 if (tevent_req_nterror(req, status)) {
2555 set_socket_options(state->fd, lp_socket_options());
2556 tevent_req_done(req);
2559 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2560 int *pfd, uint16_t *pport)
2562 struct cli_connect_sock_state *state = tevent_req_data(
2563 req, struct cli_connect_sock_state);
2566 if (tevent_req_is_nterror(req, &status)) {
2570 *pport = state->port;
2571 return NT_STATUS_OK;
2574 struct cli_connect_nb_state {
2575 const char *desthost;
2578 struct cli_state *cli;
2581 static void cli_connect_nb_done(struct tevent_req *subreq);
2583 static struct tevent_req *cli_connect_nb_send(
2584 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2585 const char *host, const struct sockaddr_storage *dest_ss,
2586 uint16_t port, int name_type, const char *myname,
2587 int signing_state, int flags)
2589 struct tevent_req *req, *subreq;
2590 struct cli_connect_nb_state *state;
2592 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2596 state->signing_state = signing_state;
2597 state->flags = flags;
2600 char *p = strchr(host, '#');
2603 name_type = strtol(p+1, NULL, 16);
2604 host = talloc_strndup(state, host, p - host);
2605 if (tevent_req_nomem(host, req)) {
2606 return tevent_req_post(req, ev);
2610 state->desthost = host;
2611 } else if (dest_ss != NULL) {
2612 state->desthost = print_canonical_sockaddr(state, dest_ss);
2613 if (tevent_req_nomem(state->desthost, req)) {
2614 return tevent_req_post(req, ev);
2617 /* No host or dest_ss given. Error out. */
2618 tevent_req_error(req, EINVAL);
2619 return tevent_req_post(req, ev);
2622 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2624 if (tevent_req_nomem(subreq, req)) {
2625 return tevent_req_post(req, ev);
2627 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2631 static void cli_connect_nb_done(struct tevent_req *subreq)
2633 struct tevent_req *req = tevent_req_callback_data(
2634 subreq, struct tevent_req);
2635 struct cli_connect_nb_state *state = tevent_req_data(
2636 req, struct cli_connect_nb_state);
2641 status = cli_connect_sock_recv(subreq, &fd, &port);
2642 TALLOC_FREE(subreq);
2643 if (tevent_req_nterror(req, status)) {
2647 state->cli = cli_state_create(state, fd, state->desthost, NULL,
2648 state->signing_state, state->flags);
2649 if (tevent_req_nomem(state->cli, req)) {
2653 tevent_req_done(req);
2656 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
2657 struct cli_state **pcli)
2659 struct cli_connect_nb_state *state = tevent_req_data(
2660 req, struct cli_connect_nb_state);
2663 if (tevent_req_is_nterror(req, &status)) {
2666 *pcli = talloc_move(NULL, &state->cli);
2667 return NT_STATUS_OK;
2670 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2671 uint16_t port, int name_type, const char *myname,
2672 int signing_state, int flags, struct cli_state **pcli)
2674 struct tevent_context *ev;
2675 struct tevent_req *req;
2676 NTSTATUS status = NT_STATUS_NO_MEMORY;
2678 ev = samba_tevent_context_init(talloc_tos());
2682 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
2683 myname, signing_state, flags);
2687 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
2690 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2693 status = cli_connect_nb_recv(req, pcli);
2699 struct cli_start_connection_state {
2700 struct tevent_context *ev;
2701 struct cli_state *cli;
2706 static void cli_start_connection_connected(struct tevent_req *subreq);
2707 static void cli_start_connection_done(struct tevent_req *subreq);
2710 establishes a connection to after the negprot.
2711 @param output_cli A fully initialised cli structure, non-null only on success
2712 @param dest_host The netbios name of the remote host
2713 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2714 @param port (optional) The destination port (0 for default)
2717 static struct tevent_req *cli_start_connection_send(
2718 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2719 const char *my_name, const char *dest_host,
2720 const struct sockaddr_storage *dest_ss, int port,
2721 int signing_state, int flags)
2723 struct tevent_req *req, *subreq;
2724 struct cli_start_connection_state *state;
2726 req = tevent_req_create(mem_ctx, &state,
2727 struct cli_start_connection_state);
2733 if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
2734 state->min_protocol = lp_client_ipc_min_protocol();
2735 state->max_protocol = lp_client_ipc_max_protocol();
2737 state->min_protocol = lp_client_min_protocol();
2738 state->max_protocol = lp_client_max_protocol();
2741 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
2742 0x20, my_name, signing_state, flags);
2743 if (tevent_req_nomem(subreq, req)) {
2744 return tevent_req_post(req, ev);
2746 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
2750 static void cli_start_connection_connected(struct tevent_req *subreq)
2752 struct tevent_req *req = tevent_req_callback_data(
2753 subreq, struct tevent_req);
2754 struct cli_start_connection_state *state = tevent_req_data(
2755 req, struct cli_start_connection_state);
2758 status = cli_connect_nb_recv(subreq, &state->cli);
2759 TALLOC_FREE(subreq);
2760 if (tevent_req_nterror(req, status)) {
2764 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
2765 state->cli->timeout,
2766 state->min_protocol,
2767 state->max_protocol,
2768 WINDOWS_CLIENT_PURE_SMB2_NEGPROT_INITIAL_CREDIT_ASK);
2769 if (tevent_req_nomem(subreq, req)) {
2772 tevent_req_set_callback(subreq, cli_start_connection_done, req);
2775 static void cli_start_connection_done(struct tevent_req *subreq)
2777 struct tevent_req *req = tevent_req_callback_data(
2778 subreq, struct tevent_req);
2779 struct cli_start_connection_state *state = tevent_req_data(
2780 req, struct cli_start_connection_state);
2783 status = smbXcli_negprot_recv(subreq);
2784 TALLOC_FREE(subreq);
2785 if (tevent_req_nterror(req, status)) {
2789 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
2790 /* Ensure we ask for some initial credits. */
2791 smb2cli_conn_set_max_credits(state->cli->conn,
2792 DEFAULT_SMB2_MAX_CREDITS);
2795 tevent_req_done(req);
2798 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
2799 struct cli_state **output_cli)
2801 struct cli_start_connection_state *state = tevent_req_data(
2802 req, struct cli_start_connection_state);
2805 if (tevent_req_is_nterror(req, &status)) {
2808 *output_cli = state->cli;
2810 return NT_STATUS_OK;
2813 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2814 const char *my_name,
2815 const char *dest_host,
2816 const struct sockaddr_storage *dest_ss, int port,
2817 int signing_state, int flags)
2819 struct tevent_context *ev;
2820 struct tevent_req *req;
2821 NTSTATUS status = NT_STATUS_NO_MEMORY;
2823 ev = samba_tevent_context_init(talloc_tos());
2827 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
2828 port, signing_state, flags);
2832 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2835 status = cli_start_connection_recv(req, output_cli);
2841 struct cli_smb1_setup_encryption_blob_state {
2846 uint16_t enc_ctx_id;
2849 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq);
2851 static struct tevent_req *cli_smb1_setup_encryption_blob_send(TALLOC_CTX *mem_ctx,
2852 struct tevent_context *ev,
2853 struct cli_state *cli,
2856 struct tevent_req *req = NULL;
2857 struct cli_smb1_setup_encryption_blob_state *state = NULL;
2858 struct tevent_req *subreq = NULL;
2860 req = tevent_req_create(mem_ctx, &state,
2861 struct cli_smb1_setup_encryption_blob_state);
2866 if (in.length > CLI_BUFFER_SIZE) {
2867 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2868 return tevent_req_post(req, ev);
2871 SSVAL(state->setup+0, 0, TRANSACT2_SETFSINFO);
2872 SSVAL(state->param, 0, 0);
2873 SSVAL(state->param, 2, SMB_REQUEST_TRANSPORT_ENCRYPTION);
2875 subreq = smb1cli_trans_send(state, ev, cli->conn,
2883 NULL, /* pipe_name */
2889 in.data, in.length, CLI_BUFFER_SIZE);
2890 if (tevent_req_nomem(subreq, req)) {
2891 return tevent_req_post(req, ev);
2893 tevent_req_set_callback(subreq,
2894 cli_smb1_setup_encryption_blob_done,
2900 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq)
2902 struct tevent_req *req =
2903 tevent_req_callback_data(subreq,
2905 struct cli_smb1_setup_encryption_blob_state *state =
2906 tevent_req_data(req,
2907 struct cli_smb1_setup_encryption_blob_state);
2908 uint8_t *rparam=NULL, *rdata=NULL;
2909 uint32_t num_rparam, num_rdata;
2912 status = smb1cli_trans_recv(subreq, state,
2913 NULL, /* recv_flags */
2914 NULL, 0, NULL, /* rsetup */
2915 &rparam, 0, &num_rparam,
2916 &rdata, 0, &num_rdata);
2917 TALLOC_FREE(subreq);
2918 state->status = status;
2919 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2920 status = NT_STATUS_OK;
2922 if (tevent_req_nterror(req, status)) {
2926 if (num_rparam == 2) {
2927 state->enc_ctx_id = SVAL(rparam, 0);
2929 TALLOC_FREE(rparam);
2931 state->out = data_blob_const(rdata, num_rdata);
2933 tevent_req_done(req);
2936 static NTSTATUS cli_smb1_setup_encryption_blob_recv(struct tevent_req *req,
2937 TALLOC_CTX *mem_ctx,
2939 uint16_t *enc_ctx_id)
2941 struct cli_smb1_setup_encryption_blob_state *state =
2942 tevent_req_data(req,
2943 struct cli_smb1_setup_encryption_blob_state);
2946 if (tevent_req_is_nterror(req, &status)) {
2947 tevent_req_received(req);
2951 status = state->status;
2954 talloc_steal(mem_ctx, out->data);
2956 *enc_ctx_id = state->enc_ctx_id;
2958 tevent_req_received(req);
2962 struct cli_smb1_setup_encryption_state {
2963 struct tevent_context *ev;
2964 struct cli_state *cli;
2965 struct smb_trans_enc_state *es;
2972 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req);
2973 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq);
2974 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req);
2975 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq);
2976 static void cli_smb1_setup_encryption_ready(struct tevent_req *req);
2978 static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
2979 struct tevent_context *ev,
2980 struct cli_state *cli,
2981 struct cli_credentials *creds)
2983 struct tevent_req *req = NULL;
2984 struct cli_smb1_setup_encryption_state *state = NULL;
2985 struct auth_generic_state *ags = NULL;
2986 const DATA_BLOB *b = NULL;
2987 bool auth_requested = false;
2988 const char *target_service = NULL;
2989 const char *target_hostname = NULL;
2992 req = tevent_req_create(mem_ctx, &state,
2993 struct cli_smb1_setup_encryption_state);
3000 auth_requested = cli_credentials_authentication_requested(creds);
3001 if (!auth_requested) {
3002 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3003 return tevent_req_post(req, ev);
3006 target_service = "cifs";
3007 target_hostname = smbXcli_conn_remote_name(cli->conn);
3009 status = cli_session_creds_prepare_krb5(cli, creds);
3010 if (tevent_req_nterror(req, status)) {
3011 return tevent_req_post(req, ev);
3014 state->es = talloc_zero(state, struct smb_trans_enc_state);
3015 if (tevent_req_nomem(state->es, req)) {
3016 return tevent_req_post(req, ev);
3019 status = auth_generic_client_prepare(state->es, &ags);
3020 if (tevent_req_nterror(req, status)) {
3021 return tevent_req_post(req, ev);
3024 gensec_want_feature(ags->gensec_security,
3025 GENSEC_FEATURE_SIGN);
3026 gensec_want_feature(ags->gensec_security,
3027 GENSEC_FEATURE_SEAL);
3029 status = auth_generic_set_creds(ags, creds);
3030 if (tevent_req_nterror(req, status)) {
3031 return tevent_req_post(req, ev);
3034 if (target_service != NULL) {
3035 status = gensec_set_target_service(ags->gensec_security,
3037 if (tevent_req_nterror(req, status)) {
3038 return tevent_req_post(req, ev);
3042 if (target_hostname != NULL) {
3043 status = gensec_set_target_hostname(ags->gensec_security,
3045 if (tevent_req_nterror(req, status)) {
3046 return tevent_req_post(req, ev);
3050 gensec_set_max_update_size(ags->gensec_security,
3053 b = smbXcli_conn_server_gss_blob(state->cli->conn);
3055 state->blob_in = *b;
3058 status = auth_generic_client_start(ags, GENSEC_OID_SPNEGO);
3059 if (tevent_req_nterror(req, status)) {
3060 return tevent_req_post(req, ev);
3064 * We only need the gensec_security part from here.
3066 state->es->gensec_security = talloc_move(state->es,
3067 &ags->gensec_security);
3070 cli_smb1_setup_encryption_local_next(req);
3071 if (!tevent_req_is_in_progress(req)) {
3072 return tevent_req_post(req, ev);
3078 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req)
3080 struct cli_smb1_setup_encryption_state *state =
3081 tevent_req_data(req,
3082 struct cli_smb1_setup_encryption_state);
3083 struct tevent_req *subreq = NULL;
3085 if (state->local_ready) {
3086 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3090 subreq = gensec_update_send(state, state->ev,
3091 state->es->gensec_security,
3093 if (tevent_req_nomem(subreq, req)) {
3096 tevent_req_set_callback(subreq, cli_smb1_setup_encryption_local_done, req);
3099 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq)
3101 struct tevent_req *req =
3102 tevent_req_callback_data(subreq,
3104 struct cli_smb1_setup_encryption_state *state =
3105 tevent_req_data(req,
3106 struct cli_smb1_setup_encryption_state);
3109 status = gensec_update_recv(subreq, state, &state->blob_out);
3110 TALLOC_FREE(subreq);
3111 state->blob_in = data_blob_null;
3112 if (!NT_STATUS_IS_OK(status) &&
3113 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3115 tevent_req_nterror(req, status);
3119 if (NT_STATUS_IS_OK(status)) {
3120 state->local_ready = true;
3124 * We always get NT_STATUS_OK from the server even if it is not ready.
3125 * So guess the server is ready when we are ready and already sent
3126 * our last blob to the server.
3128 if (state->local_ready && state->blob_out.length == 0) {
3129 state->remote_ready = true;
3132 if (state->local_ready && state->remote_ready) {
3133 cli_smb1_setup_encryption_ready(req);
3137 cli_smb1_setup_encryption_remote_next(req);
3140 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req)
3142 struct cli_smb1_setup_encryption_state *state =
3143 tevent_req_data(req,
3144 struct cli_smb1_setup_encryption_state);
3145 struct tevent_req *subreq = NULL;
3147 if (state->remote_ready) {
3148 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3152 subreq = cli_smb1_setup_encryption_blob_send(state, state->ev,
3153 state->cli, state->blob_out);
3154 if (tevent_req_nomem(subreq, req)) {
3157 tevent_req_set_callback(subreq,
3158 cli_smb1_setup_encryption_remote_done,
3162 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq)
3164 struct tevent_req *req =
3165 tevent_req_callback_data(subreq,
3167 struct cli_smb1_setup_encryption_state *state =
3168 tevent_req_data(req,
3169 struct cli_smb1_setup_encryption_state);
3172 status = cli_smb1_setup_encryption_blob_recv(subreq, state,
3174 &state->es->enc_ctx_num);
3175 TALLOC_FREE(subreq);
3176 data_blob_free(&state->blob_out);
3177 if (!NT_STATUS_IS_OK(status) &&
3178 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3180 tevent_req_nterror(req, status);
3185 * We always get NT_STATUS_OK even if the server is not ready.
3186 * So guess the server is ready when we are ready and sent
3187 * our last blob to the server.
3189 if (state->local_ready) {
3190 state->remote_ready = true;
3193 if (state->local_ready && state->remote_ready) {
3194 cli_smb1_setup_encryption_ready(req);
3198 cli_smb1_setup_encryption_local_next(req);
3201 static void cli_smb1_setup_encryption_ready(struct tevent_req *req)
3203 struct cli_smb1_setup_encryption_state *state =
3204 tevent_req_data(req,
3205 struct cli_smb1_setup_encryption_state);
3206 struct smb_trans_enc_state *es = NULL;
3208 if (state->blob_in.length != 0) {
3209 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3213 if (state->blob_out.length != 0) {
3214 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3218 es = talloc_move(state->cli->conn, &state->es);
3220 smb1cli_conn_set_encryption(state->cli->conn, es);
3223 tevent_req_done(req);
3226 static NTSTATUS cli_smb1_setup_encryption_recv(struct tevent_req *req)
3228 return tevent_req_simple_recv_ntstatus(req);
3231 NTSTATUS cli_smb1_setup_encryption(struct cli_state *cli,
3232 struct cli_credentials *creds)
3234 struct tevent_context *ev = NULL;
3235 struct tevent_req *req = NULL;
3236 NTSTATUS status = NT_STATUS_NO_MEMORY;
3238 ev = samba_tevent_context_init(talloc_tos());
3242 req = cli_smb1_setup_encryption_send(ev, ev, cli, creds);
3246 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3249 status = cli_smb1_setup_encryption_recv(req);
3256 establishes a connection right up to doing tconX, password specified.
3257 @param output_cli A fully initialised cli structure, non-null only on success
3258 @param dest_host The netbios name of the remote host
3259 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3260 @param port (optional) The destination port (0 for default)
3261 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3262 @param service_type The 'type' of serivice.
3263 @param creds The used user credentials
3266 struct cli_full_connection_creds_state {
3267 struct tevent_context *ev;
3268 const char *service;
3269 const char *service_type;
3270 struct cli_credentials *creds;
3272 struct cli_state *cli;
3275 static int cli_full_connection_creds_state_destructor(
3276 struct cli_full_connection_creds_state *s)
3278 if (s->cli != NULL) {
3279 cli_shutdown(s->cli);
3285 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq);
3286 static void cli_full_connection_creds_sess_start(struct tevent_req *req);
3287 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq);
3288 static void cli_full_connection_creds_tcon_start(struct tevent_req *req);
3289 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq);
3291 struct tevent_req *cli_full_connection_creds_send(
3292 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3293 const char *my_name, const char *dest_host,
3294 const struct sockaddr_storage *dest_ss, int port,
3295 const char *service, const char *service_type,
3296 struct cli_credentials *creds,
3297 int flags, int signing_state)
3299 struct tevent_req *req, *subreq;
3300 struct cli_full_connection_creds_state *state;
3301 enum credentials_use_kerberos krb5_state;
3302 uint32_t gensec_features = 0;
3304 req = tevent_req_create(mem_ctx, &state,
3305 struct cli_full_connection_creds_state);
3309 talloc_set_destructor(state, cli_full_connection_creds_state_destructor);
3311 flags &= ~CLI_FULL_CONNECTION_USE_KERBEROS;
3312 flags &= ~CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
3313 flags &= ~CLI_FULL_CONNECTION_USE_CCACHE;
3314 flags &= ~CLI_FULL_CONNECTION_USE_NT_HASH;
3316 krb5_state = cli_credentials_get_kerberos_state(creds);
3317 switch (krb5_state) {
3318 case CRED_MUST_USE_KERBEROS:
3319 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3320 flags &= ~CLI_FULL_CONNECTION_DONT_SPNEGO;
3322 case CRED_AUTO_USE_KERBEROS:
3323 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3324 flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
3326 case CRED_DONT_USE_KERBEROS:
3330 gensec_features = cli_credentials_get_gensec_features(creds);
3331 if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
3332 flags |= CLI_FULL_CONNECTION_USE_CCACHE;
3336 state->service = service;
3337 state->service_type = service_type;
3338 state->creds = creds;
3339 state->flags = flags;
3341 subreq = cli_start_connection_send(
3342 state, ev, my_name, dest_host, dest_ss, port,
3343 signing_state, flags);
3344 if (tevent_req_nomem(subreq, req)) {
3345 return tevent_req_post(req, ev);
3347 tevent_req_set_callback(subreq,
3348 cli_full_connection_creds_conn_done,
3353 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq)
3355 struct tevent_req *req = tevent_req_callback_data(
3356 subreq, struct tevent_req);
3357 struct cli_full_connection_creds_state *state = tevent_req_data(
3358 req, struct cli_full_connection_creds_state);
3361 status = cli_start_connection_recv(subreq, &state->cli);
3362 TALLOC_FREE(subreq);
3363 if (tevent_req_nterror(req, status)) {
3367 cli_full_connection_creds_sess_start(req);
3370 static void cli_full_connection_creds_sess_start(struct tevent_req *req)
3372 struct cli_full_connection_creds_state *state = tevent_req_data(
3373 req, struct cli_full_connection_creds_state);
3374 struct tevent_req *subreq = NULL;
3376 subreq = cli_session_setup_creds_send(
3377 state, state->ev, state->cli, state->creds);
3378 if (tevent_req_nomem(subreq, req)) {
3381 tevent_req_set_callback(subreq,
3382 cli_full_connection_creds_sess_done,
3386 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq)
3388 struct tevent_req *req = tevent_req_callback_data(
3389 subreq, struct tevent_req);
3390 struct cli_full_connection_creds_state *state = tevent_req_data(
3391 req, struct cli_full_connection_creds_state);
3394 status = cli_session_setup_creds_recv(subreq);
3395 TALLOC_FREE(subreq);
3397 if (!NT_STATUS_IS_OK(status) &&
3398 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3400 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3402 state->creds = cli_credentials_init_anon(state);
3403 if (tevent_req_nomem(state->creds, req)) {
3407 cli_full_connection_creds_sess_start(req);
3411 if (tevent_req_nterror(req, status)) {
3415 cli_full_connection_creds_tcon_start(req);
3418 static void cli_full_connection_creds_tcon_start(struct tevent_req *req)
3420 struct cli_full_connection_creds_state *state = tevent_req_data(
3421 req, struct cli_full_connection_creds_state);
3422 struct tevent_req *subreq = NULL;
3423 const char *password = NULL;
3425 if (state->service == NULL) {
3426 tevent_req_done(req);
3430 password = cli_credentials_get_password(state->creds);
3432 subreq = cli_tree_connect_send(state, state->ev,
3435 state->service_type,
3437 if (tevent_req_nomem(subreq, req)) {
3440 tevent_req_set_callback(subreq,
3441 cli_full_connection_creds_tcon_done,
3445 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq)
3447 struct tevent_req *req = tevent_req_callback_data(
3448 subreq, struct tevent_req);
3451 status = cli_tree_connect_recv(subreq);
3452 TALLOC_FREE(subreq);
3453 if (tevent_req_nterror(req, status)) {
3457 tevent_req_done(req);
3460 NTSTATUS cli_full_connection_creds_recv(struct tevent_req *req,
3461 struct cli_state **output_cli)
3463 struct cli_full_connection_creds_state *state = tevent_req_data(
3464 req, struct cli_full_connection_creds_state);
3467 if (tevent_req_is_nterror(req, &status)) {
3470 *output_cli = state->cli;
3471 talloc_set_destructor(state, NULL);
3472 return NT_STATUS_OK;
3475 NTSTATUS cli_full_connection_creds(struct cli_state **output_cli,
3476 const char *my_name,
3477 const char *dest_host,
3478 const struct sockaddr_storage *dest_ss, int port,
3479 const char *service, const char *service_type,
3480 struct cli_credentials *creds,
3484 struct tevent_context *ev;
3485 struct tevent_req *req;
3486 NTSTATUS status = NT_STATUS_NO_MEMORY;
3488 ev = samba_tevent_context_init(talloc_tos());
3492 req = cli_full_connection_creds_send(
3493 ev, ev, my_name, dest_host, dest_ss, port, service,
3494 service_type, creds, flags, signing_state);
3498 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3501 status = cli_full_connection_creds_recv(req, output_cli);
3507 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3508 const char *my_name,
3509 const char *dest_host,
3510 const struct sockaddr_storage *dest_ss, int port,
3511 const char *service, const char *service_type,
3512 const char *user, const char *domain,
3513 const char *password, int flags,
3516 TALLOC_CTX *frame = talloc_stackframe();
3518 bool use_kerberos = false;
3519 bool fallback_after_kerberos = false;
3520 bool use_ccache = false;
3521 bool pw_nt_hash = false;
3522 struct cli_credentials *creds = NULL;
3524 if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) {
3525 use_kerberos = true;
3528 if (flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) {
3529 fallback_after_kerberos = true;
3532 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
3536 if (flags & CLI_FULL_CONNECTION_USE_NT_HASH) {
3540 creds = cli_session_creds_init(frame,
3543 NULL, /* realm (use default) */
3546 fallback_after_kerberos,
3549 if (creds == NULL) {
3551 return NT_STATUS_NO_MEMORY;
3554 status = cli_full_connection_creds(output_cli, my_name,
3555 dest_host, dest_ss, port,
3556 service, service_type,
3557 creds, flags, signing_state);
3558 if (!NT_STATUS_IS_OK(status)) {
3564 return NT_STATUS_OK;
3567 /****************************************************************************
3568 Send an old style tcon.
3569 ****************************************************************************/
3570 struct cli_raw_tcon_state {
3574 static void cli_raw_tcon_done(struct tevent_req *subreq);
3576 static struct tevent_req *cli_raw_tcon_send(
3577 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3578 const char *service, const char *pass, const char *dev)
3580 struct tevent_req *req, *subreq;
3581 struct cli_raw_tcon_state *state;
3584 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3589 if (!lp_client_plaintext_auth() && (*pass)) {
3590 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3591 " or 'client ntlmv2 auth = yes'\n"));
3592 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3593 return tevent_req_post(req, ev);
3596 bytes = talloc_array(state, uint8_t, 0);
3597 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3598 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3599 service, strlen(service)+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 pass, strlen(pass)+1, NULL);
3603 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3604 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3605 dev, strlen(dev)+1, NULL);
3607 if (tevent_req_nomem(bytes, req)) {
3608 return tevent_req_post(req, ev);
3611 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3612 talloc_get_size(bytes), bytes);
3613 if (tevent_req_nomem(subreq, req)) {
3614 return tevent_req_post(req, ev);
3616 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3620 static void cli_raw_tcon_done(struct tevent_req *subreq)
3622 struct tevent_req *req = tevent_req_callback_data(
3623 subreq, struct tevent_req);
3624 struct cli_raw_tcon_state *state = tevent_req_data(
3625 req, struct cli_raw_tcon_state);
3628 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3630 TALLOC_FREE(subreq);
3631 if (tevent_req_nterror(req, status)) {
3634 tevent_req_done(req);
3637 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3638 uint16_t *max_xmit, uint16_t *tid)
3640 struct cli_raw_tcon_state *state = tevent_req_data(
3641 req, struct cli_raw_tcon_state);
3644 if (tevent_req_is_nterror(req, &status)) {
3647 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3648 *tid = SVAL(state->ret_vwv + 1, 0);
3649 return NT_STATUS_OK;
3652 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3653 const char *service, const char *pass, const char *dev,
3654 uint16_t *max_xmit, uint16_t *tid)
3656 struct tevent_context *ev;
3657 struct tevent_req *req;
3658 NTSTATUS status = NT_STATUS_NO_MEMORY;
3660 ev = samba_tevent_context_init(talloc_tos());
3664 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3668 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3671 status = cli_raw_tcon_recv(req, max_xmit, tid);
3677 /* Return a cli_state pointing at the IPC$ share for the given server */
3679 struct cli_state *get_ipc_connect(char *server,
3680 struct sockaddr_storage *server_ss,
3681 const struct user_auth_info *user_info)
3683 struct cli_state *cli;
3685 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3687 if (get_cmdline_auth_info_use_kerberos(user_info)) {
3688 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3691 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3692 get_cmdline_auth_info_username(user_info),
3694 get_cmdline_auth_info_password(user_info),
3696 SMB_SIGNING_DEFAULT);
3698 if (NT_STATUS_IS_OK(nt_status)) {
3700 } else if (is_ipaddress(server)) {
3701 /* windows 9* needs a correct NMB name for connections */
3702 fstring remote_name;
3704 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3705 cli = get_ipc_connect(remote_name, server_ss, user_info);
3714 * Given the IP address of a master browser on the network, return its
3715 * workgroup and connect to it.
3717 * This function is provided to allow additional processing beyond what
3718 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3719 * browsers and obtain each master browsers' list of domains (in case the
3720 * first master browser is recently on the network and has not yet
3721 * synchronized with other master browsers and therefore does not yet have the
3722 * entire network browse list)
3725 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3726 struct sockaddr_storage *mb_ip,
3727 const struct user_auth_info *user_info,
3728 char **pp_workgroup_out)
3730 char addr[INET6_ADDRSTRLEN];
3732 struct cli_state *cli;
3733 struct sockaddr_storage server_ss;
3735 *pp_workgroup_out = NULL;
3737 print_sockaddr(addr, sizeof(addr), mb_ip);
3738 DEBUG(99, ("Looking up name of master browser %s\n",
3742 * Do a name status query to find out the name of the master browser.
3743 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3744 * master browser will not respond to a wildcard query (or, at least,
3745 * an NT4 server acting as the domain master browser will not).
3747 * We might be able to use ONLY the query on MSBROWSE, but that's not
3748 * yet been tested with all Windows versions, so until it is, leave
3749 * the original wildcard query as the first choice and fall back to
3750 * MSBROWSE if the wildcard query fails.
3752 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3753 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3755 DEBUG(99, ("Could not retrieve name status for %s\n",
3760 if (!find_master_ip(name, &server_ss)) {
3761 DEBUG(99, ("Could not find master ip for %s\n", name));
3765 *pp_workgroup_out = talloc_strdup(ctx, name);
3767 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3769 print_sockaddr(addr, sizeof(addr), &server_ss);
3770 cli = get_ipc_connect(addr, &server_ss, user_info);
3776 * Return the IP address and workgroup of a master browser on the network, and
3780 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3781 const struct user_auth_info *user_info,
3782 char **pp_workgroup_out)
3784 struct sockaddr_storage *ip_list;
3785 struct cli_state *cli;
3789 *pp_workgroup_out = NULL;
3791 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3793 /* Go looking for workgroups by broadcasting on the local network */
3795 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3797 if (!NT_STATUS_IS_OK(status)) {
3798 DEBUG(99, ("No master browsers responded: %s\n",
3799 nt_errstr(status)));
3803 for (i = 0; i < count; i++) {
3804 char addr[INET6_ADDRSTRLEN];
3805 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3806 DEBUG(99, ("Found master browser %s\n", addr));
3808 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3809 user_info, pp_workgroup_out);