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 DEBUG(0, ("Kinit for %s to access %s failed: %s\n",
353 user_principal, target_hostname,
354 error_message(ret)));
355 if (krb5_state == CRED_MUST_USE_KERBEROS) {
357 return krb5_to_nt_status(ret);
361 * Ignore the error and hope that NTLM will work
369 /********************************************************
370 Utility function to ensure we always return at least
371 a valid char * pointer to an empty string for the
372 cli->server_os, cli->server_type and cli->server_domain
374 *******************************************************/
376 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
383 *destlen = clistr_pull_talloc(mem_ctx,
390 if (*destlen == -1) {
391 return NT_STATUS_NO_MEMORY;
395 *dest = talloc_strdup(mem_ctx, "");
397 return NT_STATUS_NO_MEMORY;
403 /****************************************************************************
404 Work out suitable capabilities to offer the server.
405 ****************************************************************************/
407 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
408 uint32_t sesssetup_capabilities)
410 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
413 * We only send capabilities based on the mask for:
414 * - client only flags
415 * - flags used in both directions
417 * We do not echo the server only flags, except some legacy flags.
419 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
420 * CAP_LARGE_WRITEX in order to allow us to do large reads
421 * against old Samba releases (<= 3.6.x).
423 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
426 * Session Setup specific flags CAP_DYNAMIC_REAUTH
427 * and CAP_EXTENDED_SECURITY are passed by the caller.
428 * We need that in order to do guest logins even if
429 * CAP_EXTENDED_SECURITY is negotiated.
431 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
432 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
433 client_capabilities |= sesssetup_capabilities;
435 return client_capabilities;
438 /****************************************************************************
439 Do a NT1 guest session setup.
440 ****************************************************************************/
442 struct cli_session_setup_guest_state {
443 struct cli_state *cli;
448 static void cli_session_setup_guest_done(struct tevent_req *subreq);
450 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
451 struct tevent_context *ev,
452 struct cli_state *cli,
453 struct tevent_req **psmbreq)
455 struct tevent_req *req, *subreq;
456 struct cli_session_setup_guest_state *state;
460 req = tevent_req_create(mem_ctx, &state,
461 struct cli_session_setup_guest_state);
468 SCVAL(vwv+0, 0, 0xFF);
471 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
473 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
474 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
479 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
481 bytes = talloc_array(state, uint8_t, 0);
483 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
485 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
487 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
488 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
495 state->bytes.iov_base = (void *)bytes;
496 state->bytes.iov_len = talloc_get_size(bytes);
498 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 0, 13,
499 vwv, 1, &state->bytes);
500 if (subreq == NULL) {
504 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
509 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
510 struct tevent_context *ev,
511 struct cli_state *cli)
513 struct tevent_req *req, *subreq;
516 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
521 status = smb1cli_req_chain_submit(&subreq, 1);
522 if (!NT_STATUS_IS_OK(status)) {
523 tevent_req_nterror(req, status);
524 return tevent_req_post(req, ev);
529 static void cli_session_setup_guest_done(struct tevent_req *subreq)
531 struct tevent_req *req = tevent_req_callback_data(
532 subreq, struct tevent_req);
533 struct cli_session_setup_guest_state *state = tevent_req_data(
534 req, struct cli_session_setup_guest_state);
535 struct cli_state *cli = state->cli;
546 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
549 if (!NT_STATUS_IS_OK(status)) {
550 tevent_req_nterror(req, status);
554 inhdr = in + NBT_HDR_SIZE;
557 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
558 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
560 status = smb_bytes_talloc_string(cli,
567 if (!NT_STATUS_IS_OK(status)) {
568 tevent_req_nterror(req, status);
573 status = smb_bytes_talloc_string(cli,
580 if (!NT_STATUS_IS_OK(status)) {
581 tevent_req_nterror(req, status);
586 status = smb_bytes_talloc_string(cli,
593 if (!NT_STATUS_IS_OK(status)) {
594 tevent_req_nterror(req, status);
599 tevent_req_done(req);
602 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
604 return tevent_req_simple_recv_ntstatus(req);
607 /* The following is calculated from :
609 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
610 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
614 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
616 struct cli_sesssetup_blob_state {
617 struct tevent_context *ev;
618 struct cli_state *cli;
620 uint16_t max_blob_size;
623 struct iovec *recv_iov;
626 const uint8_t *inbuf;
633 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
634 struct tevent_req **psubreq);
635 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
637 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
638 struct tevent_context *ev,
639 struct cli_state *cli,
642 struct tevent_req *req, *subreq;
643 struct cli_sesssetup_blob_state *state;
644 uint32_t usable_space;
646 req = tevent_req_create(mem_ctx, &state,
647 struct cli_sesssetup_blob_state);
655 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
656 usable_space = UINT16_MAX;
658 usable_space = cli_state_available_size(cli,
659 BASE_SESSSETUP_BLOB_PACKET_SIZE);
662 if (usable_space == 0) {
663 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
664 "(not possible to send %u bytes)\n",
665 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
666 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
667 return tevent_req_post(req, ev);
669 state->max_blob_size = MIN(usable_space, 0xFFFF);
671 if (!cli_sesssetup_blob_next(state, &subreq)) {
672 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
673 return tevent_req_post(req, ev);
675 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
679 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
680 struct tevent_req **psubreq)
682 struct tevent_req *subreq;
685 thistime = MIN(state->blob.length, state->max_blob_size);
687 state->this_blob.data = state->blob.data;
688 state->this_blob.length = thistime;
690 state->blob.data += thistime;
691 state->blob.length -= thistime;
693 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
694 subreq = smb2cli_session_setup_send(state, state->ev,
697 state->cli->smb2.session,
699 SMB2_CAP_DFS, /* in_capabilities */
701 0, /* in_previous_session_id */
703 if (subreq == NULL) {
707 uint16_t in_buf_size = 0;
708 uint16_t in_mpx_max = 0;
709 uint16_t in_vc_num = 0;
710 uint32_t in_sess_key = 0;
711 uint32_t in_capabilities = 0;
712 const char *in_native_os = NULL;
713 const char *in_native_lm = NULL;
715 in_buf_size = CLI_BUFFER_SIZE;
716 in_mpx_max = smbXcli_conn_max_requests(state->cli->conn);
717 in_vc_num = cli_state_get_vc_num(state->cli);
718 in_sess_key = smb1cli_conn_server_session_key(state->cli->conn);
719 in_capabilities = cli_session_setup_capabilities(state->cli,
720 CAP_EXTENDED_SECURITY);
721 in_native_os = "Unix";
722 in_native_lm = "Samba";
725 * For now we keep the same values as before,
726 * we may remove these in a separate commit later.
732 subreq = smb1cli_session_setup_ext_send(state, state->ev,
735 state->cli->smb1.pid,
736 state->cli->smb1.session,
745 if (subreq == NULL) {
753 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
755 struct tevent_req *req = tevent_req_callback_data(
756 subreq, struct tevent_req);
757 struct cli_sesssetup_blob_state *state = tevent_req_data(
758 req, struct cli_sesssetup_blob_state);
759 struct cli_state *cli = state->cli;
762 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
763 status = smb2cli_session_setup_recv(subreq, state,
767 status = smb1cli_session_setup_ext_recv(subreq, state,
771 &state->out_native_os,
772 &state->out_native_lm);
775 if (!NT_STATUS_IS_OK(status)
776 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
777 tevent_req_nterror(req, status);
781 if (cli->server_os == NULL) {
782 cli->server_os = talloc_move(cli, &state->out_native_os);
784 if (cli->server_type == NULL) {
785 cli->server_type = talloc_move(cli, &state->out_native_lm);
788 state->status = status;
790 if (state->blob.length != 0) {
794 if (!cli_sesssetup_blob_next(state, &subreq)) {
798 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
801 tevent_req_done(req);
804 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
807 const uint8_t **pinbuf,
808 struct iovec **precv_iov)
810 struct cli_sesssetup_blob_state *state = tevent_req_data(
811 req, struct cli_sesssetup_blob_state);
813 struct iovec *recv_iov;
815 if (tevent_req_is_nterror(req, &status)) {
816 TALLOC_FREE(state->cli->smb2.session);
817 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
818 tevent_req_received(req);
822 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
824 *pblob = state->ret_blob;
826 if (pinbuf != NULL) {
827 *pinbuf = state->inbuf;
829 if (precv_iov != NULL) {
830 *precv_iov = recv_iov;
832 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
833 status = state->status;
834 tevent_req_received(req);
838 /****************************************************************************
839 Do a spnego/NTLMSSP encrypted session setup.
840 ****************************************************************************/
842 struct cli_session_setup_gensec_state {
843 struct tevent_context *ev;
844 struct cli_state *cli;
845 struct auth_generic_state *auth_generic;
848 const uint8_t *inbuf;
849 struct iovec *recv_iov;
853 DATA_BLOB session_key;
856 static int cli_session_setup_gensec_state_destructor(
857 struct cli_session_setup_gensec_state *state)
859 TALLOC_FREE(state->auth_generic);
860 data_blob_clear_free(&state->session_key);
864 static void cli_session_setup_gensec_local_next(struct tevent_req *req);
865 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
866 static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
867 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
868 static void cli_session_setup_gensec_ready(struct tevent_req *req);
870 static struct tevent_req *cli_session_setup_gensec_send(
871 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
872 struct cli_credentials *creds,
873 const char *target_service,
874 const char *target_hostname)
876 struct tevent_req *req;
877 struct cli_session_setup_gensec_state *state;
879 const DATA_BLOB *b = NULL;
881 req = tevent_req_create(mem_ctx, &state,
882 struct cli_session_setup_gensec_state);
889 talloc_set_destructor(
890 state, cli_session_setup_gensec_state_destructor);
892 status = auth_generic_client_prepare(state, &state->auth_generic);
893 if (tevent_req_nterror(req, status)) {
894 return tevent_req_post(req, ev);
897 status = auth_generic_set_creds(state->auth_generic, creds);
898 if (tevent_req_nterror(req, status)) {
899 return tevent_req_post(req, ev);
902 gensec_want_feature(state->auth_generic->gensec_security,
903 GENSEC_FEATURE_SESSION_KEY);
905 if (target_service != NULL) {
906 status = gensec_set_target_service(
907 state->auth_generic->gensec_security,
909 if (tevent_req_nterror(req, status)) {
910 return tevent_req_post(req, ev);
914 if (target_hostname != NULL) {
915 status = gensec_set_target_hostname(
916 state->auth_generic->gensec_security,
918 if (tevent_req_nterror(req, status)) {
919 return tevent_req_post(req, ev);
923 b = smbXcli_conn_server_gss_blob(cli->conn);
928 state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
930 status = auth_generic_client_start(state->auth_generic,
932 if (tevent_req_nterror(req, status)) {
933 return tevent_req_post(req, ev);
936 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
937 state->cli->smb2.session = smbXcli_session_create(cli,
939 if (tevent_req_nomem(state->cli->smb2.session, req)) {
940 return tevent_req_post(req, ev);
944 cli_session_setup_gensec_local_next(req);
945 if (!tevent_req_is_in_progress(req)) {
946 return tevent_req_post(req, ev);
952 static void cli_session_setup_gensec_local_next(struct tevent_req *req)
954 struct cli_session_setup_gensec_state *state =
956 struct cli_session_setup_gensec_state);
957 struct tevent_req *subreq = NULL;
959 if (state->local_ready) {
960 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
964 subreq = gensec_update_send(state, state->ev,
965 state->auth_generic->gensec_security,
967 if (tevent_req_nomem(subreq, req)) {
970 tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
973 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
975 struct tevent_req *req =
976 tevent_req_callback_data(subreq,
978 struct cli_session_setup_gensec_state *state =
980 struct cli_session_setup_gensec_state);
983 status = gensec_update_recv(subreq, state, &state->blob_out);
985 state->blob_in = data_blob_null;
986 if (!NT_STATUS_IS_OK(status) &&
987 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
989 tevent_req_nterror(req, status);
993 if (NT_STATUS_IS_OK(status)) {
994 state->local_ready = true;
997 if (state->local_ready && state->remote_ready) {
998 cli_session_setup_gensec_ready(req);
1002 cli_session_setup_gensec_remote_next(req);
1005 static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
1007 struct cli_session_setup_gensec_state *state =
1008 tevent_req_data(req,
1009 struct cli_session_setup_gensec_state);
1010 struct tevent_req *subreq = NULL;
1012 if (state->remote_ready) {
1013 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1017 subreq = cli_sesssetup_blob_send(state, state->ev,
1018 state->cli, state->blob_out);
1019 if (tevent_req_nomem(subreq, req)) {
1022 tevent_req_set_callback(subreq,
1023 cli_session_setup_gensec_remote_done,
1027 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
1029 struct tevent_req *req =
1030 tevent_req_callback_data(subreq,
1032 struct cli_session_setup_gensec_state *state =
1033 tevent_req_data(req,
1034 struct cli_session_setup_gensec_state);
1037 state->inbuf = NULL;
1038 TALLOC_FREE(state->recv_iov);
1040 status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
1041 &state->inbuf, &state->recv_iov);
1042 TALLOC_FREE(subreq);
1043 data_blob_free(&state->blob_out);
1044 if (!NT_STATUS_IS_OK(status) &&
1045 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1047 tevent_req_nterror(req, status);
1051 if (NT_STATUS_IS_OK(status)) {
1052 struct smbXcli_session *session = NULL;
1053 bool is_guest = false;
1055 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1056 session = state->cli->smb2.session;
1058 session = state->cli->smb1.session;
1061 is_guest = smbXcli_session_is_guest(session);
1064 * We can't finish the gensec handshake, we don't
1065 * have a negotiated session key.
1067 * So just pretend we are completely done.
1069 * Note that smbXcli_session_is_guest()
1070 * always returns false if we require signing.
1072 state->blob_in = data_blob_null;
1073 state->local_ready = true;
1076 state->remote_ready = true;
1079 if (state->local_ready && state->remote_ready) {
1080 cli_session_setup_gensec_ready(req);
1084 cli_session_setup_gensec_local_next(req);
1087 static void cli_session_setup_gensec_ready(struct tevent_req *req)
1089 struct cli_session_setup_gensec_state *state =
1090 tevent_req_data(req,
1091 struct cli_session_setup_gensec_state);
1092 const char *server_domain = NULL;
1095 if (state->blob_in.length != 0) {
1096 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1100 if (state->blob_out.length != 0) {
1101 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1106 * gensec_ntlmssp_server_domain() returns NULL
1107 * if NTLMSSP is not used.
1109 * We can remove this later
1110 * and leave the server domain empty for SMB2 and above
1111 * in future releases.
1113 server_domain = gensec_ntlmssp_server_domain(
1114 state->auth_generic->gensec_security);
1116 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
1117 TALLOC_FREE(state->cli->server_domain);
1118 state->cli->server_domain = talloc_strdup(state->cli,
1120 if (state->cli->server_domain == NULL) {
1121 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1126 if (state->is_anonymous) {
1128 * Windows server does not set the
1129 * SMB2_SESSION_FLAG_IS_NULL flag.
1131 * This fix makes sure we do not try
1132 * to verify a signature on the final
1133 * session setup response.
1135 tevent_req_done(req);
1139 status = gensec_session_key(state->auth_generic->gensec_security,
1140 state, &state->session_key);
1141 if (tevent_req_nterror(req, status)) {
1145 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1146 struct smbXcli_session *session = state->cli->smb2.session;
1148 status = smb2cli_session_set_session_key(session,
1151 if (tevent_req_nterror(req, status)) {
1155 struct smbXcli_session *session = state->cli->smb1.session;
1158 status = smb1cli_session_set_session_key(session,
1159 state->session_key);
1160 if (tevent_req_nterror(req, status)) {
1164 active = smb1cli_conn_activate_signing(state->cli->conn,
1170 ok = smb1cli_conn_check_signing(state->cli->conn,
1173 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1179 tevent_req_done(req);
1182 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1184 struct cli_session_setup_gensec_state *state =
1185 tevent_req_data(req,
1186 struct cli_session_setup_gensec_state);
1189 if (tevent_req_is_nterror(req, &status)) {
1190 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1193 return NT_STATUS_OK;
1196 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1197 const char *principal)
1201 account = talloc_strdup(mem_ctx, principal);
1202 if (account == NULL) {
1205 p = strchr_m(account, '@');
1212 /****************************************************************************
1213 Do a spnego encrypted session setup.
1215 user_domain: The shortname of the domain the user/machine is a member of.
1216 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1217 ****************************************************************************/
1219 struct cli_session_setup_spnego_state {
1223 static void cli_session_setup_spnego_done(struct tevent_req *subreq);
1225 static struct tevent_req *cli_session_setup_spnego_send(
1226 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1227 struct cli_credentials *creds)
1229 struct tevent_req *req, *subreq;
1230 struct cli_session_setup_spnego_state *state;
1231 const char *target_service = NULL;
1232 const char *target_hostname = NULL;
1235 req = tevent_req_create(mem_ctx, &state,
1236 struct cli_session_setup_spnego_state);
1241 target_service = "cifs";
1242 target_hostname = smbXcli_conn_remote_name(cli->conn);
1244 status = cli_session_creds_prepare_krb5(cli, creds);
1245 if (tevent_req_nterror(req, status)) {
1246 return tevent_req_post(req, ev);;
1249 subreq = cli_session_setup_gensec_send(state, ev, cli, creds,
1250 target_service, target_hostname);
1251 if (tevent_req_nomem(subreq, req)) {
1252 return tevent_req_post(req, ev);
1254 tevent_req_set_callback(
1255 subreq, cli_session_setup_spnego_done, req);
1259 static void cli_session_setup_spnego_done(struct tevent_req *subreq)
1261 struct tevent_req *req = tevent_req_callback_data(
1262 subreq, struct tevent_req);
1265 status = cli_session_setup_gensec_recv(subreq);
1266 TALLOC_FREE(subreq);
1267 if (tevent_req_nterror(req, status)) {
1271 tevent_req_done(req);
1274 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1276 struct cli_session_setup_spnego_state *state = tevent_req_data(
1277 req, struct cli_session_setup_spnego_state);
1280 if (tevent_req_is_nterror(req, &status)) {
1281 state->result = ADS_ERROR_NT(status);
1284 return state->result;
1287 struct cli_session_setup_creds_state {
1288 struct cli_state *cli;
1289 DATA_BLOB apassword_blob;
1290 DATA_BLOB upassword_blob;
1291 DATA_BLOB lm_session_key;
1292 DATA_BLOB session_key;
1293 char *out_native_os;
1294 char *out_native_lm;
1295 char *out_primary_domain;
1298 static void cli_session_setup_creds_cleanup(struct tevent_req *req,
1299 enum tevent_req_state req_state)
1301 struct cli_session_setup_creds_state *state = tevent_req_data(
1302 req, struct cli_session_setup_creds_state);
1304 if (req_state != TEVENT_REQ_RECEIVED) {
1309 * We only call data_blob_clear() as
1310 * some of the blobs point to the same memory.
1312 * We let the talloc hierachy free the memory.
1314 data_blob_clear(&state->apassword_blob);
1315 data_blob_clear(&state->upassword_blob);
1316 data_blob_clear(&state->lm_session_key);
1317 data_blob_clear(&state->session_key);
1318 ZERO_STRUCTP(state);
1321 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq);
1322 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq);
1323 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq);
1325 /****************************************************************************
1326 Send a session setup. The username and workgroup is in UNIX character
1327 format and must be converted to DOS codepage format before sending. If the
1328 password is in plaintext, the same should be done.
1329 ****************************************************************************/
1331 struct tevent_req *cli_session_setup_creds_send(TALLOC_CTX *mem_ctx,
1332 struct tevent_context *ev,
1333 struct cli_state *cli,
1334 struct cli_credentials *creds)
1336 struct tevent_req *req, *subreq;
1337 struct cli_session_setup_creds_state *state;
1338 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1339 bool use_spnego = false;
1341 enum credentials_use_kerberos krb5_state;
1342 uint32_t gensec_features;
1343 const char *username = "";
1344 const char *domain = "";
1345 DATA_BLOB target_info = data_blob_null;
1346 DATA_BLOB challenge = data_blob_null;
1347 uint16_t in_buf_size = 0;
1348 uint16_t in_mpx_max = 0;
1349 uint16_t in_vc_num = 0;
1350 uint32_t in_sess_key = 0;
1351 const char *in_native_os = NULL;
1352 const char *in_native_lm = NULL;
1355 req = tevent_req_create(mem_ctx, &state,
1356 struct cli_session_setup_creds_state);
1362 tevent_req_set_cleanup_fn(req, cli_session_setup_creds_cleanup);
1364 krb5_state = cli_credentials_get_kerberos_state(creds);
1365 gensec_features = cli_credentials_get_gensec_features(creds);
1367 switch (krb5_state) {
1368 case CRED_MUST_USE_KERBEROS:
1369 cli->use_kerberos = true;
1370 cli->fallback_after_kerberos = false;
1372 case CRED_AUTO_USE_KERBEROS:
1373 cli->use_kerberos = true;
1374 cli->fallback_after_kerberos = true;
1376 case CRED_DONT_USE_KERBEROS:
1377 cli->use_kerberos = false;
1378 cli->fallback_after_kerberos = false;
1382 if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
1383 cli->use_ccache = true;
1385 cli->use_ccache = false;
1389 * Now work out what sort of session setup we are going to
1390 * do. I have split this into separate functions to make the flow a bit
1391 * easier to understand (tridge).
1393 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
1395 } else if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1397 } else if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
1399 * if the server supports extended security then use SPNEGO
1400 * even for anonymous connections.
1408 subreq = cli_session_setup_spnego_send(
1409 state, ev, cli, creds);
1410 if (tevent_req_nomem(subreq, req)) {
1411 return tevent_req_post(req, ev);
1413 tevent_req_set_callback(subreq, cli_session_setup_creds_done_spnego,
1418 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1420 * SessionSetupAndX was introduced by LANMAN 1.0. So we skip
1421 * this step against older servers.
1423 tevent_req_done(req);
1424 return tevent_req_post(req, ev);
1427 if (cli_credentials_is_anonymous(creds)) {
1429 * Do an anonymous session setup
1431 goto non_spnego_creds_done;
1434 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
1436 * Do an anonymous session setup,
1437 * the password is passed via the tree connect.
1439 goto non_spnego_creds_done;
1442 cli_credentials_get_ntlm_username_domain(creds, state,
1445 if (tevent_req_nomem(username, req)) {
1446 return tevent_req_post(req, ev);
1448 if (tevent_req_nomem(domain, req)) {
1449 return tevent_req_post(req, ev);
1452 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1453 bool use_unicode = smbXcli_conn_use_unicode(cli->conn);
1454 uint8_t *bytes = NULL;
1455 size_t bytes_len = 0;
1456 const char *pw = cli_credentials_get_password(creds);
1462 pw_len = strlen(pw) + 1;
1464 if (!lp_client_plaintext_auth()) {
1465 DEBUG(1, ("Server requested PLAINTEXT password but "
1466 "'client plaintext auth = no'\n"));
1467 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1468 return tevent_req_post(req, ev);
1471 bytes = talloc_array(state, uint8_t, 0);
1472 bytes = trans2_bytes_push_str(bytes, use_unicode,
1473 pw, pw_len, &bytes_len);
1474 if (tevent_req_nomem(bytes, req)) {
1475 return tevent_req_post(req, ev);
1480 * CAP_UNICODE, can only be negotiated by NT1.
1482 state->upassword_blob = data_blob_const(bytes,
1485 state->apassword_blob = data_blob_const(bytes,
1489 goto non_spnego_creds_done;
1492 challenge = data_blob_const(smb1cli_conn_server_challenge(cli->conn), 8);
1494 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1495 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
1497 * Don't send an NTLMv2 response without NTLMSSP if we
1498 * want to use spnego support.
1500 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
1501 " but 'client use spnego = yes'"
1502 " and 'client ntlmv2 auth = yes' is set\n"));
1503 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1504 return tevent_req_post(req, ev);
1507 if (lp_client_ntlmv2_auth()) {
1508 flags |= CLI_CRED_NTLMv2_AUTH;
1511 * note that the 'domain' here is a best
1512 * guess - we don't know the server's domain
1513 * at this point. Windows clients also don't
1516 target_info = NTLMv2_generate_names_blob(state,
1519 if (tevent_req_nomem(target_info.data, req)) {
1520 return tevent_req_post(req, ev);
1523 flags |= CLI_CRED_NTLM_AUTH;
1524 if (lp_client_lanman_auth()) {
1525 flags |= CLI_CRED_LANMAN_AUTH;
1529 if (!lp_client_lanman_auth()) {
1530 DEBUG(1, ("Server requested user level LM password but "
1531 "'client lanman auth = no' is set.\n"));
1532 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1533 return tevent_req_post(req, ev);
1536 flags |= CLI_CRED_LANMAN_AUTH;
1539 status = cli_credentials_get_ntlm_response(creds, state, &flags,
1542 &state->apassword_blob,
1543 &state->upassword_blob,
1544 &state->lm_session_key,
1545 &state->session_key);
1546 if (tevent_req_nterror(req, status)) {
1547 return tevent_req_post(req, ev);
1550 non_spnego_creds_done:
1552 in_buf_size = CLI_BUFFER_SIZE;
1553 in_mpx_max = smbXcli_conn_max_requests(cli->conn);
1554 in_vc_num = cli_state_get_vc_num(cli);
1555 in_sess_key = smb1cli_conn_server_session_key(cli->conn);
1556 in_native_os = "Unix";
1557 in_native_lm = "Samba";
1559 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1560 uint32_t in_capabilities = 0;
1562 in_capabilities = cli_session_setup_capabilities(cli, 0);
1565 * For now we keep the same values as before,
1566 * we may remove these in a separate commit later.
1570 subreq = smb1cli_session_setup_nt1_send(state, ev,
1581 state->apassword_blob,
1582 state->upassword_blob,
1586 if (tevent_req_nomem(subreq, req)) {
1587 return tevent_req_post(req, ev);
1589 tevent_req_set_callback(subreq, cli_session_setup_creds_done_nt1,
1595 * For now we keep the same values as before,
1596 * we may remove these in a separate commit later.
1601 subreq = smb1cli_session_setup_lm21_send(state, ev,
1612 state->apassword_blob,
1615 if (tevent_req_nomem(subreq, req)) {
1616 return tevent_req_post(req, ev);
1618 tevent_req_set_callback(subreq, cli_session_setup_creds_done_lm21,
1623 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq)
1625 struct tevent_req *req = tevent_req_callback_data(
1626 subreq, struct tevent_req);
1629 status = cli_session_setup_spnego_recv(subreq);
1630 TALLOC_FREE(subreq);
1631 if (!ADS_ERR_OK(status)) {
1632 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1633 tevent_req_nterror(req, ads_ntstatus(status));
1636 tevent_req_done(req);
1639 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq)
1641 struct tevent_req *req = tevent_req_callback_data(
1642 subreq, struct tevent_req);
1643 struct cli_session_setup_creds_state *state = tevent_req_data(
1644 req, struct cli_session_setup_creds_state);
1645 struct cli_state *cli = state->cli;
1647 struct iovec *recv_iov = NULL;
1648 const uint8_t *inbuf = NULL;
1651 status = smb1cli_session_setup_nt1_recv(subreq, state,
1654 &state->out_native_os,
1655 &state->out_native_lm,
1656 &state->out_primary_domain);
1657 TALLOC_FREE(subreq);
1658 if (!NT_STATUS_IS_OK(status)) {
1659 DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
1660 tevent_req_nterror(req, status);
1664 if (cli->server_os == NULL) {
1665 cli->server_os = talloc_move(cli, &state->out_native_os);
1667 if (cli->server_type == NULL) {
1668 cli->server_type = talloc_move(cli, &state->out_native_lm);
1670 if (cli->server_domain == NULL) {
1671 cli->server_domain = talloc_move(cli, &state->out_primary_domain);
1674 ok = smb1cli_conn_activate_signing(cli->conn,
1676 state->upassword_blob);
1678 ok = smb1cli_conn_check_signing(cli->conn, inbuf, 1);
1680 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1685 if (state->session_key.data) {
1686 struct smbXcli_session *session = cli->smb1.session;
1688 status = smb1cli_session_set_session_key(session,
1689 state->session_key);
1690 if (tevent_req_nterror(req, status)) {
1695 tevent_req_done(req);
1698 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq)
1700 struct tevent_req *req = tevent_req_callback_data(
1701 subreq, struct tevent_req);
1702 struct cli_session_setup_creds_state *state = tevent_req_data(
1703 req, struct cli_session_setup_creds_state);
1704 struct cli_state *cli = state->cli;
1707 status = smb1cli_session_setup_lm21_recv(subreq, state,
1708 &state->out_native_os,
1709 &state->out_native_lm);
1710 TALLOC_FREE(subreq);
1711 if (!NT_STATUS_IS_OK(status)) {
1712 DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
1713 tevent_req_nterror(req, status);
1717 if (cli->server_os == NULL) {
1718 cli->server_os = talloc_move(cli, &state->out_native_os);
1720 if (cli->server_type == NULL) {
1721 cli->server_type = talloc_move(cli, &state->out_native_lm);
1724 tevent_req_done(req);
1727 NTSTATUS cli_session_setup_creds_recv(struct tevent_req *req)
1729 return tevent_req_simple_recv_ntstatus(req);
1732 NTSTATUS cli_session_setup_creds(struct cli_state *cli,
1733 struct cli_credentials *creds)
1735 struct tevent_context *ev;
1736 struct tevent_req *req;
1737 NTSTATUS status = NT_STATUS_NO_MEMORY;
1739 if (smbXcli_conn_has_async_calls(cli->conn)) {
1740 return NT_STATUS_INVALID_PARAMETER;
1742 ev = samba_tevent_context_init(talloc_tos());
1746 req = cli_session_setup_creds_send(ev, ev, cli, creds);
1750 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1753 status = cli_session_setup_creds_recv(req);
1759 NTSTATUS cli_session_setup_anon(struct cli_state *cli)
1761 NTSTATUS status = NT_STATUS_NO_MEMORY;
1762 struct cli_credentials *creds = NULL;
1764 creds = cli_credentials_init_anon(cli);
1765 if (creds == NULL) {
1766 return NT_STATUS_NO_MEMORY;
1769 status = cli_session_setup_creds(cli, creds);
1771 if (!NT_STATUS_IS_OK(status)) {
1775 return NT_STATUS_OK;
1778 /****************************************************************************
1780 *****************************************************************************/
1782 struct cli_ulogoff_state {
1783 struct cli_state *cli;
1787 static void cli_ulogoff_done(struct tevent_req *subreq);
1789 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1790 struct tevent_context *ev,
1791 struct cli_state *cli)
1793 struct tevent_req *req, *subreq;
1794 struct cli_ulogoff_state *state;
1796 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1802 SCVAL(state->vwv+0, 0, 0xFF);
1803 SCVAL(state->vwv+1, 0, 0);
1804 SSVAL(state->vwv+2, 0, 0);
1806 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
1808 if (tevent_req_nomem(subreq, req)) {
1809 return tevent_req_post(req, ev);
1811 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1815 static void cli_ulogoff_done(struct tevent_req *subreq)
1817 struct tevent_req *req = tevent_req_callback_data(
1818 subreq, struct tevent_req);
1819 struct cli_ulogoff_state *state = tevent_req_data(
1820 req, struct cli_ulogoff_state);
1823 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1824 if (!NT_STATUS_IS_OK(status)) {
1825 tevent_req_nterror(req, status);
1828 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1829 tevent_req_done(req);
1832 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1834 return tevent_req_simple_recv_ntstatus(req);
1837 NTSTATUS cli_ulogoff(struct cli_state *cli)
1839 struct tevent_context *ev;
1840 struct tevent_req *req;
1841 NTSTATUS status = NT_STATUS_NO_MEMORY;
1843 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1844 status = smb2cli_logoff(cli->conn,
1847 if (!NT_STATUS_IS_OK(status)) {
1850 smb2cli_session_set_id_and_flags(cli->smb2.session,
1852 return NT_STATUS_OK;
1855 if (smbXcli_conn_has_async_calls(cli->conn)) {
1856 return NT_STATUS_INVALID_PARAMETER;
1858 ev = samba_tevent_context_init(talloc_tos());
1862 req = cli_ulogoff_send(ev, ev, cli);
1866 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1869 status = cli_ulogoff_recv(req);
1875 /****************************************************************************
1877 ****************************************************************************/
1879 struct cli_tcon_andx_state {
1880 struct cli_state *cli;
1885 static void cli_tcon_andx_done(struct tevent_req *subreq);
1887 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1888 struct tevent_context *ev,
1889 struct cli_state *cli,
1890 const char *share, const char *dev,
1891 const char *pass, int passlen,
1892 struct tevent_req **psmbreq)
1894 struct tevent_req *req, *subreq;
1895 struct cli_tcon_andx_state *state;
1900 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1901 uint16_t tcon_flags = 0;
1905 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1912 cli->share = talloc_strdup(cli, share);
1917 /* in user level security don't send a password now */
1918 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1921 } else if (pass == NULL) {
1922 DEBUG(1, ("Server not using user level security and no "
1923 "password supplied.\n"));
1927 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1928 *pass && passlen != 24) {
1929 if (!lp_client_lanman_auth()) {
1930 DEBUG(1, ("Server requested LANMAN password "
1931 "(share-level security) but "
1932 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
1937 * Non-encrypted passwords - convert to DOS codepage before
1940 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
1942 pass = (const char *)p24;
1944 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1945 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1949 if (!lp_client_plaintext_auth() && (*pass)) {
1950 DEBUG(1, ("Server requested PLAINTEXT "
1952 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
1957 * Non-encrypted passwords - convert to DOS codepage
1960 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
1961 if (tevent_req_nomem(tmp_pass, req)) {
1962 return tevent_req_post(req, ev);
1964 tmp_pass = trans2_bytes_push_str(tmp_pass,
1965 false, /* always DOS */
1969 if (tevent_req_nomem(tmp_pass, req)) {
1970 return tevent_req_post(req, ev);
1972 pass = (const char *)tmp_pass;
1973 passlen = talloc_get_size(tmp_pass);
1977 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
1978 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
1980 SCVAL(vwv+0, 0, 0xFF);
1983 SSVAL(vwv+2, 0, tcon_flags);
1984 SSVAL(vwv+3, 0, passlen);
1986 if (passlen && pass) {
1987 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
1989 bytes = talloc_array(state, uint8_t, 0);
1995 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1996 smbXcli_conn_remote_name(cli->conn), share);
2001 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2006 * Add the devicetype
2008 tmp = talloc_strdup_upper(talloc_tos(), dev);
2013 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2016 if (bytes == NULL) {
2021 state->bytes.iov_base = (void *)bytes;
2022 state->bytes.iov_len = talloc_get_size(bytes);
2024 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
2026 if (subreq == NULL) {
2030 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2035 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2036 return tevent_req_post(req, ev);
2039 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2040 struct tevent_context *ev,
2041 struct cli_state *cli,
2042 const char *share, const char *dev,
2043 const char *pass, int passlen)
2045 struct tevent_req *req, *subreq;
2048 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2053 if (subreq == NULL) {
2056 status = smb1cli_req_chain_submit(&subreq, 1);
2057 if (!NT_STATUS_IS_OK(status)) {
2058 tevent_req_nterror(req, status);
2059 return tevent_req_post(req, ev);
2064 static void cli_tcon_andx_done(struct tevent_req *subreq)
2066 struct tevent_req *req = tevent_req_callback_data(
2067 subreq, struct tevent_req);
2068 struct cli_tcon_andx_state *state = tevent_req_data(
2069 req, struct cli_tcon_andx_state);
2070 struct cli_state *cli = state->cli;
2078 uint16_t optional_support = 0;
2080 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2081 &num_bytes, &bytes);
2082 TALLOC_FREE(subreq);
2083 if (!NT_STATUS_IS_OK(status)) {
2084 tevent_req_nterror(req, status);
2088 inhdr = in + NBT_HDR_SIZE;
2091 if (clistr_pull_talloc(cli,
2092 (const char *)inhdr,
2093 SVAL(inhdr, HDR_FLG2),
2097 STR_TERMINATE|STR_ASCII) == -1) {
2098 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2102 cli->dev = talloc_strdup(cli, "");
2103 if (cli->dev == NULL) {
2104 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2109 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2110 /* almost certainly win95 - enable bug fixes */
2115 * Make sure that we have the optional support 16-bit field. WCT > 2.
2116 * Avoids issues when connecting to Win9x boxes sharing files
2119 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2120 optional_support = SVAL(vwv+2, 0);
2123 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2124 smb1cli_session_protect_session_key(cli->smb1.session);
2127 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2128 SVAL(inhdr, HDR_TID),
2130 0, /* maximal_access */
2131 0, /* guest_maximal_access */
2133 NULL); /* fs_type */
2135 tevent_req_done(req);
2138 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2140 return tevent_req_simple_recv_ntstatus(req);
2143 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2144 const char *dev, const char *pass, int passlen)
2146 TALLOC_CTX *frame = talloc_stackframe();
2147 struct tevent_context *ev;
2148 struct tevent_req *req;
2149 NTSTATUS status = NT_STATUS_NO_MEMORY;
2151 if (smbXcli_conn_has_async_calls(cli->conn)) {
2153 * Can't use sync call while an async call is in flight
2155 status = NT_STATUS_INVALID_PARAMETER;
2159 ev = samba_tevent_context_init(frame);
2164 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2169 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2173 status = cli_tcon_andx_recv(req);
2179 struct cli_tree_connect_state {
2180 struct cli_state *cli;
2183 static struct tevent_req *cli_raw_tcon_send(
2184 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2185 const char *service, const char *pass, const char *dev);
2186 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2187 uint16_t *max_xmit, uint16_t *tid);
2189 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2190 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2191 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2193 static struct tevent_req *cli_tree_connect_send(
2194 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2195 const char *share, const char *dev, const char *pass)
2197 struct tevent_req *req, *subreq;
2198 struct cli_tree_connect_state *state;
2204 passlen = strlen(pass) + 1;
2206 req = tevent_req_create(mem_ctx, &state,
2207 struct cli_tree_connect_state);
2213 cli->share = talloc_strdup(cli, share);
2214 if (tevent_req_nomem(cli->share, req)) {
2215 return tevent_req_post(req, ev);
2218 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2221 cli->smb2.tcon = smbXcli_tcon_create(cli);
2222 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2223 return tevent_req_post(req, ev);
2226 unc = talloc_asprintf(state, "\\\\%s\\%s",
2227 smbXcli_conn_remote_name(cli->conn),
2229 if (tevent_req_nomem(unc, req)) {
2230 return tevent_req_post(req, ev);
2233 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2234 cli->smb2.session, cli->smb2.tcon,
2237 if (tevent_req_nomem(subreq, req)) {
2238 return tevent_req_post(req, ev);
2240 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2245 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2246 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2248 if (tevent_req_nomem(subreq, req)) {
2249 return tevent_req_post(req, ev);
2251 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2256 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2257 if (tevent_req_nomem(subreq, req)) {
2258 return tevent_req_post(req, ev);
2260 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2265 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2267 tevent_req_simple_finish_ntstatus(
2268 subreq, smb2cli_tcon_recv(subreq));
2271 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2273 tevent_req_simple_finish_ntstatus(
2274 subreq, cli_tcon_andx_recv(subreq));
2277 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2279 struct tevent_req *req = tevent_req_callback_data(
2280 subreq, struct tevent_req);
2281 struct cli_tree_connect_state *state = tevent_req_data(
2282 req, struct cli_tree_connect_state);
2284 uint16_t max_xmit = 0;
2287 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2288 if (tevent_req_nterror(req, status)) {
2292 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2294 0, /* optional_support */
2295 0, /* maximal_access */
2296 0, /* guest_maximal_access */
2298 NULL); /* fs_type */
2300 tevent_req_done(req);
2303 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2305 return tevent_req_simple_recv_ntstatus(req);
2308 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2309 const char *dev, const char *pass)
2311 struct tevent_context *ev;
2312 struct tevent_req *req;
2313 NTSTATUS status = NT_STATUS_NO_MEMORY;
2315 if (smbXcli_conn_has_async_calls(cli->conn)) {
2316 return NT_STATUS_INVALID_PARAMETER;
2318 ev = samba_tevent_context_init(talloc_tos());
2322 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass);
2326 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2329 status = cli_tree_connect_recv(req);
2335 NTSTATUS cli_tree_connect_creds(struct cli_state *cli,
2336 const char *share, const char *dev,
2337 struct cli_credentials *creds)
2339 const char *pw = NULL;
2341 if (creds != NULL) {
2342 pw = cli_credentials_get_password(creds);
2345 return cli_tree_connect(cli, share, dev, pw);
2348 /****************************************************************************
2349 Send a tree disconnect.
2350 ****************************************************************************/
2352 struct cli_tdis_state {
2353 struct cli_state *cli;
2356 static void cli_tdis_done(struct tevent_req *subreq);
2358 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2359 struct tevent_context *ev,
2360 struct cli_state *cli)
2362 struct tevent_req *req, *subreq;
2363 struct cli_tdis_state *state;
2365 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2371 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2372 if (tevent_req_nomem(subreq, req)) {
2373 return tevent_req_post(req, ev);
2375 tevent_req_set_callback(subreq, cli_tdis_done, req);
2379 static void cli_tdis_done(struct tevent_req *subreq)
2381 struct tevent_req *req = tevent_req_callback_data(
2382 subreq, struct tevent_req);
2383 struct cli_tdis_state *state = tevent_req_data(
2384 req, struct cli_tdis_state);
2387 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2388 TALLOC_FREE(subreq);
2389 if (!NT_STATUS_IS_OK(status)) {
2390 tevent_req_nterror(req, status);
2393 cli_state_set_tid(state->cli, UINT16_MAX);
2394 tevent_req_done(req);
2397 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2399 return tevent_req_simple_recv_ntstatus(req);
2402 NTSTATUS cli_tdis(struct cli_state *cli)
2404 struct tevent_context *ev;
2405 struct tevent_req *req;
2406 NTSTATUS status = NT_STATUS_NO_MEMORY;
2408 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2409 return smb2cli_tdis(cli->conn,
2415 if (smbXcli_conn_has_async_calls(cli->conn)) {
2416 return NT_STATUS_INVALID_PARAMETER;
2418 ev = samba_tevent_context_init(talloc_tos());
2422 req = cli_tdis_send(ev, ev, cli);
2426 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2429 status = cli_tdis_recv(req);
2435 struct cli_connect_sock_state {
2436 const char **called_names;
2437 const char **calling_names;
2443 static void cli_connect_sock_done(struct tevent_req *subreq);
2446 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2450 static struct tevent_req *cli_connect_sock_send(
2451 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2452 const char *host, int name_type, const struct sockaddr_storage *pss,
2453 const char *myname, uint16_t port)
2455 struct tevent_req *req, *subreq;
2456 struct cli_connect_sock_state *state;
2458 struct sockaddr_storage *addrs;
2459 unsigned i, num_addrs;
2462 req = tevent_req_create(mem_ctx, &state,
2463 struct cli_connect_sock_state);
2468 prog = getenv("LIBSMB_PROG");
2470 state->fd = sock_exec(prog);
2471 if (state->fd == -1) {
2472 status = map_nt_error_from_unix(errno);
2473 tevent_req_nterror(req, status);
2476 tevent_req_done(req);
2478 return tevent_req_post(req, ev);
2481 if ((pss == NULL) || is_zero_addr(pss)) {
2484 * Here we cheat. resolve_name_list is not async at all. So
2485 * this call will only be really async if the name lookup has
2486 * been done externally.
2489 status = resolve_name_list(state, host, name_type,
2490 &addrs, &num_addrs);
2491 if (!NT_STATUS_IS_OK(status)) {
2492 tevent_req_nterror(req, status);
2493 return tevent_req_post(req, ev);
2496 addrs = talloc_array(state, struct sockaddr_storage, 1);
2497 if (tevent_req_nomem(addrs, req)) {
2498 return tevent_req_post(req, ev);
2504 state->called_names = talloc_array(state, const char *, num_addrs);
2505 if (tevent_req_nomem(state->called_names, req)) {
2506 return tevent_req_post(req, ev);
2508 state->called_types = talloc_array(state, int, num_addrs);
2509 if (tevent_req_nomem(state->called_types, req)) {
2510 return tevent_req_post(req, ev);
2512 state->calling_names = talloc_array(state, const char *, num_addrs);
2513 if (tevent_req_nomem(state->calling_names, req)) {
2514 return tevent_req_post(req, ev);
2516 for (i=0; i<num_addrs; i++) {
2517 state->called_names[i] = host;
2518 state->called_types[i] = name_type;
2519 state->calling_names[i] = myname;
2522 subreq = smbsock_any_connect_send(
2523 state, ev, addrs, state->called_names, state->called_types,
2524 state->calling_names, NULL, num_addrs, port);
2525 if (tevent_req_nomem(subreq, req)) {
2526 return tevent_req_post(req, ev);
2528 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2532 static void cli_connect_sock_done(struct tevent_req *subreq)
2534 struct tevent_req *req = tevent_req_callback_data(
2535 subreq, struct tevent_req);
2536 struct cli_connect_sock_state *state = tevent_req_data(
2537 req, struct cli_connect_sock_state);
2540 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2542 TALLOC_FREE(subreq);
2543 if (tevent_req_nterror(req, status)) {
2546 set_socket_options(state->fd, lp_socket_options());
2547 tevent_req_done(req);
2550 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2551 int *pfd, uint16_t *pport)
2553 struct cli_connect_sock_state *state = tevent_req_data(
2554 req, struct cli_connect_sock_state);
2557 if (tevent_req_is_nterror(req, &status)) {
2561 *pport = state->port;
2562 return NT_STATUS_OK;
2565 struct cli_connect_nb_state {
2566 const char *desthost;
2569 struct cli_state *cli;
2572 static void cli_connect_nb_done(struct tevent_req *subreq);
2574 static struct tevent_req *cli_connect_nb_send(
2575 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2576 const char *host, const struct sockaddr_storage *dest_ss,
2577 uint16_t port, int name_type, const char *myname,
2578 int signing_state, int flags)
2580 struct tevent_req *req, *subreq;
2581 struct cli_connect_nb_state *state;
2583 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2587 state->signing_state = signing_state;
2588 state->flags = flags;
2591 char *p = strchr(host, '#');
2594 name_type = strtol(p+1, NULL, 16);
2595 host = talloc_strndup(state, host, p - host);
2596 if (tevent_req_nomem(host, req)) {
2597 return tevent_req_post(req, ev);
2601 state->desthost = host;
2602 } else if (dest_ss != NULL) {
2603 state->desthost = print_canonical_sockaddr(state, dest_ss);
2604 if (tevent_req_nomem(state->desthost, req)) {
2605 return tevent_req_post(req, ev);
2608 /* No host or dest_ss given. Error out. */
2609 tevent_req_error(req, EINVAL);
2610 return tevent_req_post(req, ev);
2613 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2615 if (tevent_req_nomem(subreq, req)) {
2616 return tevent_req_post(req, ev);
2618 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2622 static void cli_connect_nb_done(struct tevent_req *subreq)
2624 struct tevent_req *req = tevent_req_callback_data(
2625 subreq, struct tevent_req);
2626 struct cli_connect_nb_state *state = tevent_req_data(
2627 req, struct cli_connect_nb_state);
2632 status = cli_connect_sock_recv(subreq, &fd, &port);
2633 TALLOC_FREE(subreq);
2634 if (tevent_req_nterror(req, status)) {
2638 state->cli = cli_state_create(state, fd, state->desthost, NULL,
2639 state->signing_state, state->flags);
2640 if (tevent_req_nomem(state->cli, req)) {
2644 tevent_req_done(req);
2647 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
2648 struct cli_state **pcli)
2650 struct cli_connect_nb_state *state = tevent_req_data(
2651 req, struct cli_connect_nb_state);
2654 if (tevent_req_is_nterror(req, &status)) {
2657 *pcli = talloc_move(NULL, &state->cli);
2658 return NT_STATUS_OK;
2661 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2662 uint16_t port, int name_type, const char *myname,
2663 int signing_state, int flags, struct cli_state **pcli)
2665 struct tevent_context *ev;
2666 struct tevent_req *req;
2667 NTSTATUS status = NT_STATUS_NO_MEMORY;
2669 ev = samba_tevent_context_init(talloc_tos());
2673 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
2674 myname, signing_state, flags);
2678 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
2681 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2684 status = cli_connect_nb_recv(req, pcli);
2690 struct cli_start_connection_state {
2691 struct tevent_context *ev;
2692 struct cli_state *cli;
2697 static void cli_start_connection_connected(struct tevent_req *subreq);
2698 static void cli_start_connection_done(struct tevent_req *subreq);
2701 establishes a connection to after the negprot.
2702 @param output_cli A fully initialised cli structure, non-null only on success
2703 @param dest_host The netbios name of the remote host
2704 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2705 @param port (optional) The destination port (0 for default)
2708 static struct tevent_req *cli_start_connection_send(
2709 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2710 const char *my_name, const char *dest_host,
2711 const struct sockaddr_storage *dest_ss, int port,
2712 int signing_state, int flags)
2714 struct tevent_req *req, *subreq;
2715 struct cli_start_connection_state *state;
2717 req = tevent_req_create(mem_ctx, &state,
2718 struct cli_start_connection_state);
2724 if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
2725 state->min_protocol = lp_client_ipc_min_protocol();
2726 state->max_protocol = lp_client_ipc_max_protocol();
2728 state->min_protocol = lp_client_min_protocol();
2729 state->max_protocol = lp_client_max_protocol();
2732 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
2733 0x20, my_name, signing_state, flags);
2734 if (tevent_req_nomem(subreq, req)) {
2735 return tevent_req_post(req, ev);
2737 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
2741 static void cli_start_connection_connected(struct tevent_req *subreq)
2743 struct tevent_req *req = tevent_req_callback_data(
2744 subreq, struct tevent_req);
2745 struct cli_start_connection_state *state = tevent_req_data(
2746 req, struct cli_start_connection_state);
2749 status = cli_connect_nb_recv(subreq, &state->cli);
2750 TALLOC_FREE(subreq);
2751 if (tevent_req_nterror(req, status)) {
2755 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
2756 state->cli->timeout,
2757 state->min_protocol,
2758 state->max_protocol,
2759 WINDOWS_CLIENT_PURE_SMB2_NEGPROT_INITIAL_CREDIT_ASK);
2760 if (tevent_req_nomem(subreq, req)) {
2763 tevent_req_set_callback(subreq, cli_start_connection_done, req);
2766 static void cli_start_connection_done(struct tevent_req *subreq)
2768 struct tevent_req *req = tevent_req_callback_data(
2769 subreq, struct tevent_req);
2770 struct cli_start_connection_state *state = tevent_req_data(
2771 req, struct cli_start_connection_state);
2774 status = smbXcli_negprot_recv(subreq);
2775 TALLOC_FREE(subreq);
2776 if (tevent_req_nterror(req, status)) {
2780 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
2781 /* Ensure we ask for some initial credits. */
2782 smb2cli_conn_set_max_credits(state->cli->conn,
2783 DEFAULT_SMB2_MAX_CREDITS);
2786 tevent_req_done(req);
2789 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
2790 struct cli_state **output_cli)
2792 struct cli_start_connection_state *state = tevent_req_data(
2793 req, struct cli_start_connection_state);
2796 if (tevent_req_is_nterror(req, &status)) {
2799 *output_cli = state->cli;
2801 return NT_STATUS_OK;
2804 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2805 const char *my_name,
2806 const char *dest_host,
2807 const struct sockaddr_storage *dest_ss, int port,
2808 int signing_state, int flags)
2810 struct tevent_context *ev;
2811 struct tevent_req *req;
2812 NTSTATUS status = NT_STATUS_NO_MEMORY;
2814 ev = samba_tevent_context_init(talloc_tos());
2818 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
2819 port, signing_state, flags);
2823 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2826 status = cli_start_connection_recv(req, output_cli);
2832 struct cli_smb1_setup_encryption_blob_state {
2837 uint16_t enc_ctx_id;
2840 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq);
2842 static struct tevent_req *cli_smb1_setup_encryption_blob_send(TALLOC_CTX *mem_ctx,
2843 struct tevent_context *ev,
2844 struct cli_state *cli,
2847 struct tevent_req *req = NULL;
2848 struct cli_smb1_setup_encryption_blob_state *state = NULL;
2849 struct tevent_req *subreq = NULL;
2851 req = tevent_req_create(mem_ctx, &state,
2852 struct cli_smb1_setup_encryption_blob_state);
2857 if (in.length > CLI_BUFFER_SIZE) {
2858 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2859 return tevent_req_post(req, ev);
2862 SSVAL(state->setup+0, 0, TRANSACT2_SETFSINFO);
2863 SSVAL(state->param, 0, 0);
2864 SSVAL(state->param, 2, SMB_REQUEST_TRANSPORT_ENCRYPTION);
2866 subreq = smb1cli_trans_send(state, ev, cli->conn,
2874 NULL, /* pipe_name */
2880 in.data, in.length, CLI_BUFFER_SIZE);
2881 if (tevent_req_nomem(subreq, req)) {
2882 return tevent_req_post(req, ev);
2884 tevent_req_set_callback(subreq,
2885 cli_smb1_setup_encryption_blob_done,
2891 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq)
2893 struct tevent_req *req =
2894 tevent_req_callback_data(subreq,
2896 struct cli_smb1_setup_encryption_blob_state *state =
2897 tevent_req_data(req,
2898 struct cli_smb1_setup_encryption_blob_state);
2899 uint8_t *rparam=NULL, *rdata=NULL;
2900 uint32_t num_rparam, num_rdata;
2903 status = smb1cli_trans_recv(subreq, state,
2904 NULL, /* recv_flags */
2905 NULL, 0, NULL, /* rsetup */
2906 &rparam, 0, &num_rparam,
2907 &rdata, 0, &num_rdata);
2908 TALLOC_FREE(subreq);
2909 state->status = status;
2910 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2911 status = NT_STATUS_OK;
2913 if (tevent_req_nterror(req, status)) {
2917 if (num_rparam == 2) {
2918 state->enc_ctx_id = SVAL(rparam, 0);
2920 TALLOC_FREE(rparam);
2922 state->out = data_blob_const(rdata, num_rdata);
2924 tevent_req_done(req);
2927 static NTSTATUS cli_smb1_setup_encryption_blob_recv(struct tevent_req *req,
2928 TALLOC_CTX *mem_ctx,
2930 uint16_t *enc_ctx_id)
2932 struct cli_smb1_setup_encryption_blob_state *state =
2933 tevent_req_data(req,
2934 struct cli_smb1_setup_encryption_blob_state);
2937 if (tevent_req_is_nterror(req, &status)) {
2938 tevent_req_received(req);
2942 status = state->status;
2945 talloc_steal(mem_ctx, out->data);
2947 *enc_ctx_id = state->enc_ctx_id;
2949 tevent_req_received(req);
2953 struct cli_smb1_setup_encryption_state {
2954 struct tevent_context *ev;
2955 struct cli_state *cli;
2956 struct smb_trans_enc_state *es;
2963 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req);
2964 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq);
2965 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req);
2966 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq);
2967 static void cli_smb1_setup_encryption_ready(struct tevent_req *req);
2969 static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
2970 struct tevent_context *ev,
2971 struct cli_state *cli,
2972 struct cli_credentials *creds)
2974 struct tevent_req *req = NULL;
2975 struct cli_smb1_setup_encryption_state *state = NULL;
2976 struct auth_generic_state *ags = NULL;
2977 const DATA_BLOB *b = NULL;
2978 bool auth_requested = false;
2979 const char *target_service = NULL;
2980 const char *target_hostname = NULL;
2983 req = tevent_req_create(mem_ctx, &state,
2984 struct cli_smb1_setup_encryption_state);
2991 auth_requested = cli_credentials_authentication_requested(creds);
2992 if (!auth_requested) {
2993 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2994 return tevent_req_post(req, ev);
2997 target_service = "cifs";
2998 target_hostname = smbXcli_conn_remote_name(cli->conn);
3000 status = cli_session_creds_prepare_krb5(cli, creds);
3001 if (tevent_req_nterror(req, status)) {
3002 return tevent_req_post(req, ev);
3005 state->es = talloc_zero(state, struct smb_trans_enc_state);
3006 if (tevent_req_nomem(state->es, req)) {
3007 return tevent_req_post(req, ev);
3010 status = auth_generic_client_prepare(state->es, &ags);
3011 if (tevent_req_nterror(req, status)) {
3012 return tevent_req_post(req, ev);
3015 gensec_want_feature(ags->gensec_security,
3016 GENSEC_FEATURE_SIGN);
3017 gensec_want_feature(ags->gensec_security,
3018 GENSEC_FEATURE_SEAL);
3020 status = auth_generic_set_creds(ags, creds);
3021 if (tevent_req_nterror(req, status)) {
3022 return tevent_req_post(req, ev);
3025 if (target_service != NULL) {
3026 status = gensec_set_target_service(ags->gensec_security,
3028 if (tevent_req_nterror(req, status)) {
3029 return tevent_req_post(req, ev);
3033 if (target_hostname != NULL) {
3034 status = gensec_set_target_hostname(ags->gensec_security,
3036 if (tevent_req_nterror(req, status)) {
3037 return tevent_req_post(req, ev);
3041 gensec_set_max_update_size(ags->gensec_security,
3044 b = smbXcli_conn_server_gss_blob(state->cli->conn);
3046 state->blob_in = *b;
3049 status = auth_generic_client_start(ags, GENSEC_OID_SPNEGO);
3050 if (tevent_req_nterror(req, status)) {
3051 return tevent_req_post(req, ev);
3055 * We only need the gensec_security part from here.
3057 state->es->gensec_security = talloc_move(state->es,
3058 &ags->gensec_security);
3061 cli_smb1_setup_encryption_local_next(req);
3062 if (!tevent_req_is_in_progress(req)) {
3063 return tevent_req_post(req, ev);
3069 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req)
3071 struct cli_smb1_setup_encryption_state *state =
3072 tevent_req_data(req,
3073 struct cli_smb1_setup_encryption_state);
3074 struct tevent_req *subreq = NULL;
3076 if (state->local_ready) {
3077 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3081 subreq = gensec_update_send(state, state->ev,
3082 state->es->gensec_security,
3084 if (tevent_req_nomem(subreq, req)) {
3087 tevent_req_set_callback(subreq, cli_smb1_setup_encryption_local_done, req);
3090 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq)
3092 struct tevent_req *req =
3093 tevent_req_callback_data(subreq,
3095 struct cli_smb1_setup_encryption_state *state =
3096 tevent_req_data(req,
3097 struct cli_smb1_setup_encryption_state);
3100 status = gensec_update_recv(subreq, state, &state->blob_out);
3101 TALLOC_FREE(subreq);
3102 state->blob_in = data_blob_null;
3103 if (!NT_STATUS_IS_OK(status) &&
3104 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3106 tevent_req_nterror(req, status);
3110 if (NT_STATUS_IS_OK(status)) {
3111 state->local_ready = true;
3115 * We always get NT_STATUS_OK from the server even if it is not ready.
3116 * So guess the server is ready when we are ready and already sent
3117 * our last blob to the server.
3119 if (state->local_ready && state->blob_out.length == 0) {
3120 state->remote_ready = true;
3123 if (state->local_ready && state->remote_ready) {
3124 cli_smb1_setup_encryption_ready(req);
3128 cli_smb1_setup_encryption_remote_next(req);
3131 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req)
3133 struct cli_smb1_setup_encryption_state *state =
3134 tevent_req_data(req,
3135 struct cli_smb1_setup_encryption_state);
3136 struct tevent_req *subreq = NULL;
3138 if (state->remote_ready) {
3139 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3143 subreq = cli_smb1_setup_encryption_blob_send(state, state->ev,
3144 state->cli, state->blob_out);
3145 if (tevent_req_nomem(subreq, req)) {
3148 tevent_req_set_callback(subreq,
3149 cli_smb1_setup_encryption_remote_done,
3153 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq)
3155 struct tevent_req *req =
3156 tevent_req_callback_data(subreq,
3158 struct cli_smb1_setup_encryption_state *state =
3159 tevent_req_data(req,
3160 struct cli_smb1_setup_encryption_state);
3163 status = cli_smb1_setup_encryption_blob_recv(subreq, state,
3165 &state->es->enc_ctx_num);
3166 TALLOC_FREE(subreq);
3167 data_blob_free(&state->blob_out);
3168 if (!NT_STATUS_IS_OK(status) &&
3169 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3171 tevent_req_nterror(req, status);
3176 * We always get NT_STATUS_OK even if the server is not ready.
3177 * So guess the server is ready when we are ready and sent
3178 * our last blob to the server.
3180 if (state->local_ready) {
3181 state->remote_ready = true;
3184 if (state->local_ready && state->remote_ready) {
3185 cli_smb1_setup_encryption_ready(req);
3189 cli_smb1_setup_encryption_local_next(req);
3192 static void cli_smb1_setup_encryption_ready(struct tevent_req *req)
3194 struct cli_smb1_setup_encryption_state *state =
3195 tevent_req_data(req,
3196 struct cli_smb1_setup_encryption_state);
3197 struct smb_trans_enc_state *es = NULL;
3199 if (state->blob_in.length != 0) {
3200 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3204 if (state->blob_out.length != 0) {
3205 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3209 es = talloc_move(state->cli->conn, &state->es);
3211 smb1cli_conn_set_encryption(state->cli->conn, es);
3214 tevent_req_done(req);
3217 static NTSTATUS cli_smb1_setup_encryption_recv(struct tevent_req *req)
3219 return tevent_req_simple_recv_ntstatus(req);
3222 NTSTATUS cli_smb1_setup_encryption(struct cli_state *cli,
3223 struct cli_credentials *creds)
3225 struct tevent_context *ev = NULL;
3226 struct tevent_req *req = NULL;
3227 NTSTATUS status = NT_STATUS_NO_MEMORY;
3229 ev = samba_tevent_context_init(talloc_tos());
3233 req = cli_smb1_setup_encryption_send(ev, ev, cli, creds);
3237 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3240 status = cli_smb1_setup_encryption_recv(req);
3247 establishes a connection right up to doing tconX, password specified.
3248 @param output_cli A fully initialised cli structure, non-null only on success
3249 @param dest_host The netbios name of the remote host
3250 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3251 @param port (optional) The destination port (0 for default)
3252 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3253 @param service_type The 'type' of serivice.
3254 @param creds The used user credentials
3257 struct cli_full_connection_creds_state {
3258 struct tevent_context *ev;
3259 const char *service;
3260 const char *service_type;
3261 struct cli_credentials *creds;
3263 struct cli_state *cli;
3266 static int cli_full_connection_creds_state_destructor(
3267 struct cli_full_connection_creds_state *s)
3269 if (s->cli != NULL) {
3270 cli_shutdown(s->cli);
3276 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq);
3277 static void cli_full_connection_creds_sess_start(struct tevent_req *req);
3278 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq);
3279 static void cli_full_connection_creds_tcon_start(struct tevent_req *req);
3280 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq);
3282 struct tevent_req *cli_full_connection_creds_send(
3283 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3284 const char *my_name, const char *dest_host,
3285 const struct sockaddr_storage *dest_ss, int port,
3286 const char *service, const char *service_type,
3287 struct cli_credentials *creds,
3288 int flags, int signing_state)
3290 struct tevent_req *req, *subreq;
3291 struct cli_full_connection_creds_state *state;
3292 enum credentials_use_kerberos krb5_state;
3293 uint32_t gensec_features = 0;
3295 req = tevent_req_create(mem_ctx, &state,
3296 struct cli_full_connection_creds_state);
3300 talloc_set_destructor(state, cli_full_connection_creds_state_destructor);
3302 flags &= ~CLI_FULL_CONNECTION_USE_KERBEROS;
3303 flags &= ~CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
3304 flags &= ~CLI_FULL_CONNECTION_USE_CCACHE;
3305 flags &= ~CLI_FULL_CONNECTION_USE_NT_HASH;
3307 krb5_state = cli_credentials_get_kerberos_state(creds);
3308 switch (krb5_state) {
3309 case CRED_MUST_USE_KERBEROS:
3310 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3311 flags &= ~CLI_FULL_CONNECTION_DONT_SPNEGO;
3313 case CRED_AUTO_USE_KERBEROS:
3314 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3315 flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
3317 case CRED_DONT_USE_KERBEROS:
3321 gensec_features = cli_credentials_get_gensec_features(creds);
3322 if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
3323 flags |= CLI_FULL_CONNECTION_USE_CCACHE;
3327 state->service = service;
3328 state->service_type = service_type;
3329 state->creds = creds;
3330 state->flags = flags;
3332 subreq = cli_start_connection_send(
3333 state, ev, my_name, dest_host, dest_ss, port,
3334 signing_state, flags);
3335 if (tevent_req_nomem(subreq, req)) {
3336 return tevent_req_post(req, ev);
3338 tevent_req_set_callback(subreq,
3339 cli_full_connection_creds_conn_done,
3344 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq)
3346 struct tevent_req *req = tevent_req_callback_data(
3347 subreq, struct tevent_req);
3348 struct cli_full_connection_creds_state *state = tevent_req_data(
3349 req, struct cli_full_connection_creds_state);
3352 status = cli_start_connection_recv(subreq, &state->cli);
3353 TALLOC_FREE(subreq);
3354 if (tevent_req_nterror(req, status)) {
3358 cli_full_connection_creds_sess_start(req);
3361 static void cli_full_connection_creds_sess_start(struct tevent_req *req)
3363 struct cli_full_connection_creds_state *state = tevent_req_data(
3364 req, struct cli_full_connection_creds_state);
3365 struct tevent_req *subreq = NULL;
3367 subreq = cli_session_setup_creds_send(
3368 state, state->ev, state->cli, state->creds);
3369 if (tevent_req_nomem(subreq, req)) {
3372 tevent_req_set_callback(subreq,
3373 cli_full_connection_creds_sess_done,
3377 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq)
3379 struct tevent_req *req = tevent_req_callback_data(
3380 subreq, struct tevent_req);
3381 struct cli_full_connection_creds_state *state = tevent_req_data(
3382 req, struct cli_full_connection_creds_state);
3385 status = cli_session_setup_creds_recv(subreq);
3386 TALLOC_FREE(subreq);
3388 if (!NT_STATUS_IS_OK(status) &&
3389 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3391 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3393 state->creds = cli_credentials_init_anon(state);
3394 if (tevent_req_nomem(state->creds, req)) {
3398 cli_full_connection_creds_sess_start(req);
3402 if (tevent_req_nterror(req, status)) {
3406 cli_full_connection_creds_tcon_start(req);
3409 static void cli_full_connection_creds_tcon_start(struct tevent_req *req)
3411 struct cli_full_connection_creds_state *state = tevent_req_data(
3412 req, struct cli_full_connection_creds_state);
3413 struct tevent_req *subreq = NULL;
3414 const char *password = NULL;
3416 if (state->service == NULL) {
3417 tevent_req_done(req);
3421 password = cli_credentials_get_password(state->creds);
3423 subreq = cli_tree_connect_send(state, state->ev,
3426 state->service_type,
3428 if (tevent_req_nomem(subreq, req)) {
3431 tevent_req_set_callback(subreq,
3432 cli_full_connection_creds_tcon_done,
3436 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq)
3438 struct tevent_req *req = tevent_req_callback_data(
3439 subreq, struct tevent_req);
3442 status = cli_tree_connect_recv(subreq);
3443 TALLOC_FREE(subreq);
3444 if (tevent_req_nterror(req, status)) {
3448 tevent_req_done(req);
3451 NTSTATUS cli_full_connection_creds_recv(struct tevent_req *req,
3452 struct cli_state **output_cli)
3454 struct cli_full_connection_creds_state *state = tevent_req_data(
3455 req, struct cli_full_connection_creds_state);
3458 if (tevent_req_is_nterror(req, &status)) {
3461 *output_cli = state->cli;
3462 talloc_set_destructor(state, NULL);
3463 return NT_STATUS_OK;
3466 NTSTATUS cli_full_connection_creds(struct cli_state **output_cli,
3467 const char *my_name,
3468 const char *dest_host,
3469 const struct sockaddr_storage *dest_ss, int port,
3470 const char *service, const char *service_type,
3471 struct cli_credentials *creds,
3475 struct tevent_context *ev;
3476 struct tevent_req *req;
3477 NTSTATUS status = NT_STATUS_NO_MEMORY;
3479 ev = samba_tevent_context_init(talloc_tos());
3483 req = cli_full_connection_creds_send(
3484 ev, ev, my_name, dest_host, dest_ss, port, service,
3485 service_type, creds, flags, signing_state);
3489 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3492 status = cli_full_connection_creds_recv(req, output_cli);
3498 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3499 const char *my_name,
3500 const char *dest_host,
3501 const struct sockaddr_storage *dest_ss, int port,
3502 const char *service, const char *service_type,
3503 const char *user, const char *domain,
3504 const char *password, int flags,
3507 TALLOC_CTX *frame = talloc_stackframe();
3509 bool use_kerberos = false;
3510 bool fallback_after_kerberos = false;
3511 bool use_ccache = false;
3512 bool pw_nt_hash = false;
3513 struct cli_credentials *creds = NULL;
3515 if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) {
3516 use_kerberos = true;
3519 if (flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) {
3520 fallback_after_kerberos = true;
3523 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
3527 if (flags & CLI_FULL_CONNECTION_USE_NT_HASH) {
3531 creds = cli_session_creds_init(frame,
3534 NULL, /* realm (use default) */
3537 fallback_after_kerberos,
3540 if (creds == NULL) {
3542 return NT_STATUS_NO_MEMORY;
3545 status = cli_full_connection_creds(output_cli, my_name,
3546 dest_host, dest_ss, port,
3547 service, service_type,
3548 creds, flags, signing_state);
3549 if (!NT_STATUS_IS_OK(status)) {
3555 return NT_STATUS_OK;
3558 /****************************************************************************
3559 Send an old style tcon.
3560 ****************************************************************************/
3561 struct cli_raw_tcon_state {
3565 static void cli_raw_tcon_done(struct tevent_req *subreq);
3567 static struct tevent_req *cli_raw_tcon_send(
3568 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3569 const char *service, const char *pass, const char *dev)
3571 struct tevent_req *req, *subreq;
3572 struct cli_raw_tcon_state *state;
3575 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3580 if (!lp_client_plaintext_auth() && (*pass)) {
3581 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3582 " or 'client ntlmv2 auth = yes'\n"));
3583 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3584 return tevent_req_post(req, ev);
3587 bytes = talloc_array(state, uint8_t, 0);
3588 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3589 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3590 service, strlen(service)+1, NULL);
3591 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3592 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3593 pass, strlen(pass)+1, NULL);
3594 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3595 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3596 dev, strlen(dev)+1, NULL);
3598 if (tevent_req_nomem(bytes, req)) {
3599 return tevent_req_post(req, ev);
3602 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3603 talloc_get_size(bytes), bytes);
3604 if (tevent_req_nomem(subreq, req)) {
3605 return tevent_req_post(req, ev);
3607 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3611 static void cli_raw_tcon_done(struct tevent_req *subreq)
3613 struct tevent_req *req = tevent_req_callback_data(
3614 subreq, struct tevent_req);
3615 struct cli_raw_tcon_state *state = tevent_req_data(
3616 req, struct cli_raw_tcon_state);
3619 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3621 TALLOC_FREE(subreq);
3622 if (tevent_req_nterror(req, status)) {
3625 tevent_req_done(req);
3628 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3629 uint16_t *max_xmit, uint16_t *tid)
3631 struct cli_raw_tcon_state *state = tevent_req_data(
3632 req, struct cli_raw_tcon_state);
3635 if (tevent_req_is_nterror(req, &status)) {
3638 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3639 *tid = SVAL(state->ret_vwv + 1, 0);
3640 return NT_STATUS_OK;
3643 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3644 const char *service, const char *pass, const char *dev,
3645 uint16_t *max_xmit, uint16_t *tid)
3647 struct tevent_context *ev;
3648 struct tevent_req *req;
3649 NTSTATUS status = NT_STATUS_NO_MEMORY;
3651 ev = samba_tevent_context_init(talloc_tos());
3655 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3659 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3662 status = cli_raw_tcon_recv(req, max_xmit, tid);
3668 /* Return a cli_state pointing at the IPC$ share for the given server */
3670 struct cli_state *get_ipc_connect(char *server,
3671 struct sockaddr_storage *server_ss,
3672 const struct user_auth_info *user_info)
3674 struct cli_state *cli;
3676 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3678 if (get_cmdline_auth_info_use_kerberos(user_info)) {
3679 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3682 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3683 get_cmdline_auth_info_username(user_info),
3685 get_cmdline_auth_info_password(user_info),
3687 SMB_SIGNING_DEFAULT);
3689 if (NT_STATUS_IS_OK(nt_status)) {
3691 } else if (is_ipaddress(server)) {
3692 /* windows 9* needs a correct NMB name for connections */
3693 fstring remote_name;
3695 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3696 cli = get_ipc_connect(remote_name, server_ss, user_info);
3705 * Given the IP address of a master browser on the network, return its
3706 * workgroup and connect to it.
3708 * This function is provided to allow additional processing beyond what
3709 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3710 * browsers and obtain each master browsers' list of domains (in case the
3711 * first master browser is recently on the network and has not yet
3712 * synchronized with other master browsers and therefore does not yet have the
3713 * entire network browse list)
3716 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3717 struct sockaddr_storage *mb_ip,
3718 const struct user_auth_info *user_info,
3719 char **pp_workgroup_out)
3721 char addr[INET6_ADDRSTRLEN];
3723 struct cli_state *cli;
3724 struct sockaddr_storage server_ss;
3726 *pp_workgroup_out = NULL;
3728 print_sockaddr(addr, sizeof(addr), mb_ip);
3729 DEBUG(99, ("Looking up name of master browser %s\n",
3733 * Do a name status query to find out the name of the master browser.
3734 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3735 * master browser will not respond to a wildcard query (or, at least,
3736 * an NT4 server acting as the domain master browser will not).
3738 * We might be able to use ONLY the query on MSBROWSE, but that's not
3739 * yet been tested with all Windows versions, so until it is, leave
3740 * the original wildcard query as the first choice and fall back to
3741 * MSBROWSE if the wildcard query fails.
3743 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3744 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3746 DEBUG(99, ("Could not retrieve name status for %s\n",
3751 if (!find_master_ip(name, &server_ss)) {
3752 DEBUG(99, ("Could not find master ip for %s\n", name));
3756 *pp_workgroup_out = talloc_strdup(ctx, name);
3758 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3760 print_sockaddr(addr, sizeof(addr), &server_ss);
3761 cli = get_ipc_connect(addr, &server_ss, user_info);
3767 * Return the IP address and workgroup of a master browser on the network, and
3771 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3772 const struct user_auth_info *user_info,
3773 char **pp_workgroup_out)
3775 struct sockaddr_storage *ip_list;
3776 struct cli_state *cli;
3780 *pp_workgroup_out = NULL;
3782 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3784 /* Go looking for workgroups by broadcasting on the local network */
3786 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3788 if (!NT_STATUS_IS_OK(status)) {
3789 DEBUG(99, ("No master browsers responded: %s\n",
3790 nt_errstr(status)));
3794 for (i = 0; i < count; i++) {
3795 char addr[INET6_ADDRSTRLEN];
3796 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3797 DEBUG(99, ("Found master browser %s\n", addr));
3799 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3800 user_info, pp_workgroup_out);