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"
43 #define STAR_SMBSERVER "*SMBSERVER"
45 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
46 const char *principal);
48 struct cli_credentials *cli_session_creds_init(TALLOC_CTX *mem_ctx,
54 bool fallback_after_kerberos,
56 bool password_is_nt_hash)
58 struct loadparm_context *lp_ctx = NULL;
59 struct cli_credentials *creds = NULL;
60 const char *principal = NULL;
65 creds = cli_credentials_init(mem_ctx);
70 lp_ctx = loadparm_init_s3(creds, loadparm_s3_helpers());
74 cli_credentials_set_conf(creds, lp_ctx);
76 if (username == NULL) {
80 if (strlen(username) == 0) {
81 if (password != NULL && strlen(password) == 0) {
83 * some callers pass "" as no password
85 * gensec only handles NULL as no password.
89 if (password == NULL) {
90 cli_credentials_set_anonymous(creds);
95 tmp = talloc_strdup(creds, username);
101 /* allow for workgroups as part of the username */
102 if ((p = strchr_m(tmp, '\\')) ||
103 (p = strchr_m(tmp, '/')) ||
104 (p = strchr_m(tmp, *lp_winbind_separator()))) {
110 principal = username;
111 username = cli_session_setup_get_account(creds, principal);
112 if (username == NULL) {
115 ok = strequal(username, principal);
118 * Ok still the same, so it's not a principal
123 if (use_kerberos && fallback_after_kerberos) {
124 cli_credentials_set_kerberos_state(creds,
125 CRED_AUTO_USE_KERBEROS);
126 } else if (use_kerberos) {
127 cli_credentials_set_kerberos_state(creds,
128 CRED_MUST_USE_KERBEROS);
130 cli_credentials_set_kerberos_state(creds,
131 CRED_DONT_USE_KERBEROS);
137 features = cli_credentials_get_gensec_features(creds);
138 features |= GENSEC_FEATURE_NTLM_CCACHE;
139 cli_credentials_set_gensec_features(creds, features);
141 if (password != NULL && strlen(password) == 0) {
143 * some callers pass "" as no password
145 * GENSEC_FEATURE_NTLM_CCACHE only handles
146 * NULL as no password.
152 ok = cli_credentials_set_username(creds,
159 if (domain != NULL) {
160 ok = cli_credentials_set_domain(creds,
168 if (principal != NULL) {
169 ok = cli_credentials_set_principal(creds,
178 ok = cli_credentials_set_realm(creds,
186 if (password != NULL && strlen(password) > 0) {
187 if (password_is_nt_hash) {
188 struct samr_Password nt_hash;
191 converted = strhex_to_str((char *)nt_hash.hash,
192 sizeof(nt_hash.hash),
195 if (converted != sizeof(nt_hash.hash)) {
199 ok = cli_credentials_set_nt_hash(creds,
206 ok = cli_credentials_set_password(creds,
221 NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli,
222 struct cli_credentials *creds)
224 TALLOC_CTX *frame = talloc_stackframe();
225 const char *user_principal = NULL;
226 const char *user_account = NULL;
227 const char *user_domain = NULL;
228 const char *pass = NULL;
229 const char *target_hostname = NULL;
230 const DATA_BLOB *server_blob = NULL;
231 enum credentials_use_kerberos krb5_state;
232 bool try_kerberos = false;
233 bool need_kinit = false;
234 bool auth_requested = true;
237 target_hostname = smbXcli_conn_remote_name(cli->conn);
238 if (!cli->got_kerberos_mechanism) {
239 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 cli->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 (!cli->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 if (tevent_req_nomem(subreq, req)) {
2762 tevent_req_set_callback(subreq, cli_start_connection_done, req);
2765 static void cli_start_connection_done(struct tevent_req *subreq)
2767 struct tevent_req *req = tevent_req_callback_data(
2768 subreq, struct tevent_req);
2769 struct cli_start_connection_state *state = tevent_req_data(
2770 req, struct cli_start_connection_state);
2773 status = smbXcli_negprot_recv(subreq);
2774 TALLOC_FREE(subreq);
2775 if (tevent_req_nterror(req, status)) {
2779 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
2780 /* Ensure we ask for some initial credits. */
2781 smb2cli_conn_set_max_credits(state->cli->conn,
2782 DEFAULT_SMB2_MAX_CREDITS);
2785 tevent_req_done(req);
2788 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
2789 struct cli_state **output_cli)
2791 struct cli_start_connection_state *state = tevent_req_data(
2792 req, struct cli_start_connection_state);
2795 if (tevent_req_is_nterror(req, &status)) {
2798 *output_cli = state->cli;
2800 return NT_STATUS_OK;
2803 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2804 const char *my_name,
2805 const char *dest_host,
2806 const struct sockaddr_storage *dest_ss, int port,
2807 int signing_state, int flags)
2809 struct tevent_context *ev;
2810 struct tevent_req *req;
2811 NTSTATUS status = NT_STATUS_NO_MEMORY;
2813 ev = samba_tevent_context_init(talloc_tos());
2817 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
2818 port, signing_state, flags);
2822 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2825 status = cli_start_connection_recv(req, output_cli);
2831 struct cli_smb1_setup_encryption_blob_state {
2836 uint16_t enc_ctx_id;
2839 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq);
2841 static struct tevent_req *cli_smb1_setup_encryption_blob_send(TALLOC_CTX *mem_ctx,
2842 struct tevent_context *ev,
2843 struct cli_state *cli,
2846 struct tevent_req *req = NULL;
2847 struct cli_smb1_setup_encryption_blob_state *state = NULL;
2848 struct tevent_req *subreq = NULL;
2850 req = tevent_req_create(mem_ctx, &state,
2851 struct cli_smb1_setup_encryption_blob_state);
2856 if (in.length > CLI_BUFFER_SIZE) {
2857 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2858 return tevent_req_post(req, ev);
2861 SSVAL(state->setup+0, 0, TRANSACT2_SETFSINFO);
2862 SSVAL(state->param, 0, 0);
2863 SSVAL(state->param, 2, SMB_REQUEST_TRANSPORT_ENCRYPTION);
2865 subreq = smb1cli_trans_send(state, ev, cli->conn,
2873 NULL, /* pipe_name */
2879 in.data, in.length, CLI_BUFFER_SIZE);
2880 if (tevent_req_nomem(subreq, req)) {
2881 return tevent_req_post(req, ev);
2883 tevent_req_set_callback(subreq,
2884 cli_smb1_setup_encryption_blob_done,
2890 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq)
2892 struct tevent_req *req =
2893 tevent_req_callback_data(subreq,
2895 struct cli_smb1_setup_encryption_blob_state *state =
2896 tevent_req_data(req,
2897 struct cli_smb1_setup_encryption_blob_state);
2898 uint8_t *rparam=NULL, *rdata=NULL;
2899 uint32_t num_rparam, num_rdata;
2902 status = smb1cli_trans_recv(subreq, state,
2903 NULL, /* recv_flags */
2904 NULL, 0, NULL, /* rsetup */
2905 &rparam, 0, &num_rparam,
2906 &rdata, 0, &num_rdata);
2907 TALLOC_FREE(subreq);
2908 state->status = status;
2909 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2910 status = NT_STATUS_OK;
2912 if (tevent_req_nterror(req, status)) {
2916 if (num_rparam == 2) {
2917 state->enc_ctx_id = SVAL(rparam, 0);
2919 TALLOC_FREE(rparam);
2921 state->out = data_blob_const(rdata, num_rdata);
2923 tevent_req_done(req);
2926 static NTSTATUS cli_smb1_setup_encryption_blob_recv(struct tevent_req *req,
2927 TALLOC_CTX *mem_ctx,
2929 uint16_t *enc_ctx_id)
2931 struct cli_smb1_setup_encryption_blob_state *state =
2932 tevent_req_data(req,
2933 struct cli_smb1_setup_encryption_blob_state);
2936 if (tevent_req_is_nterror(req, &status)) {
2937 tevent_req_received(req);
2941 status = state->status;
2944 talloc_steal(mem_ctx, out->data);
2946 *enc_ctx_id = state->enc_ctx_id;
2948 tevent_req_received(req);
2952 struct cli_smb1_setup_encryption_state {
2953 struct tevent_context *ev;
2954 struct cli_state *cli;
2955 struct smb_trans_enc_state *es;
2962 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req);
2963 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq);
2964 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req);
2965 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq);
2966 static void cli_smb1_setup_encryption_ready(struct tevent_req *req);
2968 static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
2969 struct tevent_context *ev,
2970 struct cli_state *cli,
2971 struct cli_credentials *creds)
2973 struct tevent_req *req = NULL;
2974 struct cli_smb1_setup_encryption_state *state = NULL;
2975 struct auth_generic_state *ags = NULL;
2976 const DATA_BLOB *b = NULL;
2977 bool auth_requested = false;
2978 enum credentials_use_kerberos krb5_state;
2979 const char *mech_oid = NULL;
2980 const char *target_service = NULL;
2981 const char *target_hostname = NULL;
2984 req = tevent_req_create(mem_ctx, &state,
2985 struct cli_smb1_setup_encryption_state);
2992 auth_requested = cli_credentials_authentication_requested(creds);
2993 if (!auth_requested) {
2994 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2995 return tevent_req_post(req, ev);
2998 target_service = "cifs";
2999 target_hostname = smbXcli_conn_remote_name(cli->conn);
3001 krb5_state = cli_credentials_get_kerberos_state(creds);
3002 if (krb5_state == CRED_MUST_USE_KERBEROS) {
3003 mech_oid = GENSEC_OID_SPNEGO;
3005 b = smbXcli_conn_server_gss_blob(state->cli->conn);
3007 state->blob_in = *b;
3010 status = cli_session_creds_prepare_krb5(cli, creds);
3011 if (tevent_req_nterror(req, status)) {
3012 return tevent_req_post(req, ev);
3016 * Be compatible with the <= 4.5 client code,
3017 * which used raw NTLMSSP unless kerberos
3020 * We need to check with the oldest server implementation
3021 * if we can remove this and always use
3022 * GENSEC_OID_SPNEGO.
3024 mech_oid = GENSEC_OID_NTLMSSP;
3027 state->es = talloc_zero(state, struct smb_trans_enc_state);
3028 if (tevent_req_nomem(state->es, req)) {
3029 return tevent_req_post(req, ev);
3032 status = auth_generic_client_prepare(state->es, &ags);
3033 if (tevent_req_nterror(req, status)) {
3034 return tevent_req_post(req, ev);
3037 gensec_want_feature(ags->gensec_security,
3038 GENSEC_FEATURE_SIGN);
3039 gensec_want_feature(ags->gensec_security,
3040 GENSEC_FEATURE_SEAL);
3042 status = auth_generic_set_creds(ags, creds);
3043 if (tevent_req_nterror(req, status)) {
3044 return tevent_req_post(req, ev);
3047 if (target_service != NULL) {
3048 status = gensec_set_target_service(ags->gensec_security,
3050 if (tevent_req_nterror(req, status)) {
3051 return tevent_req_post(req, ev);
3055 if (target_hostname != NULL) {
3056 status = gensec_set_target_hostname(ags->gensec_security,
3058 if (tevent_req_nterror(req, status)) {
3059 return tevent_req_post(req, ev);
3063 gensec_set_max_update_size(ags->gensec_security,
3066 status = auth_generic_client_start(ags, mech_oid);
3067 if (tevent_req_nterror(req, status)) {
3068 return tevent_req_post(req, ev);
3072 * We only need the gensec_security part from here.
3074 state->es->gensec_security = talloc_move(state->es,
3075 &ags->gensec_security);
3078 cli_smb1_setup_encryption_local_next(req);
3079 if (!tevent_req_is_in_progress(req)) {
3080 return tevent_req_post(req, ev);
3086 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req)
3088 struct cli_smb1_setup_encryption_state *state =
3089 tevent_req_data(req,
3090 struct cli_smb1_setup_encryption_state);
3091 struct tevent_req *subreq = NULL;
3093 if (state->local_ready) {
3094 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3098 subreq = gensec_update_send(state, state->ev,
3099 state->es->gensec_security,
3101 if (tevent_req_nomem(subreq, req)) {
3104 tevent_req_set_callback(subreq, cli_smb1_setup_encryption_local_done, req);
3107 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq)
3109 struct tevent_req *req =
3110 tevent_req_callback_data(subreq,
3112 struct cli_smb1_setup_encryption_state *state =
3113 tevent_req_data(req,
3114 struct cli_smb1_setup_encryption_state);
3117 status = gensec_update_recv(subreq, state, &state->blob_out);
3118 TALLOC_FREE(subreq);
3119 state->blob_in = data_blob_null;
3120 if (!NT_STATUS_IS_OK(status) &&
3121 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3123 tevent_req_nterror(req, status);
3127 if (NT_STATUS_IS_OK(status)) {
3128 state->local_ready = true;
3132 * We always get NT_STATUS_OK from the server even if it is not ready.
3133 * So guess the server is ready when we are ready and already sent
3134 * our last blob to the server.
3136 if (state->local_ready && state->blob_out.length == 0) {
3137 state->remote_ready = true;
3140 if (state->local_ready && state->remote_ready) {
3141 cli_smb1_setup_encryption_ready(req);
3145 cli_smb1_setup_encryption_remote_next(req);
3148 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req)
3150 struct cli_smb1_setup_encryption_state *state =
3151 tevent_req_data(req,
3152 struct cli_smb1_setup_encryption_state);
3153 struct tevent_req *subreq = NULL;
3155 if (state->remote_ready) {
3156 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3160 subreq = cli_smb1_setup_encryption_blob_send(state, state->ev,
3161 state->cli, state->blob_out);
3162 if (tevent_req_nomem(subreq, req)) {
3165 tevent_req_set_callback(subreq,
3166 cli_smb1_setup_encryption_remote_done,
3170 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq)
3172 struct tevent_req *req =
3173 tevent_req_callback_data(subreq,
3175 struct cli_smb1_setup_encryption_state *state =
3176 tevent_req_data(req,
3177 struct cli_smb1_setup_encryption_state);
3180 status = cli_smb1_setup_encryption_blob_recv(subreq, state,
3182 &state->es->enc_ctx_num);
3183 TALLOC_FREE(subreq);
3184 data_blob_free(&state->blob_out);
3185 if (!NT_STATUS_IS_OK(status) &&
3186 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3188 tevent_req_nterror(req, status);
3193 * We always get NT_STATUS_OK even if the server is not ready.
3194 * So guess the server is ready when we are ready and sent
3195 * our last blob to the server.
3197 if (state->local_ready) {
3198 state->remote_ready = true;
3201 if (state->local_ready && state->remote_ready) {
3202 cli_smb1_setup_encryption_ready(req);
3206 cli_smb1_setup_encryption_local_next(req);
3209 static void cli_smb1_setup_encryption_ready(struct tevent_req *req)
3211 struct cli_smb1_setup_encryption_state *state =
3212 tevent_req_data(req,
3213 struct cli_smb1_setup_encryption_state);
3214 struct smb_trans_enc_state *es = NULL;
3216 if (state->blob_in.length != 0) {
3217 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3221 if (state->blob_out.length != 0) {
3222 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3226 es = talloc_move(state->cli->conn, &state->es);
3228 smb1cli_conn_set_encryption(state->cli->conn, es);
3231 tevent_req_done(req);
3234 static NTSTATUS cli_smb1_setup_encryption_recv(struct tevent_req *req)
3236 return tevent_req_simple_recv_ntstatus(req);
3239 NTSTATUS cli_smb1_setup_encryption(struct cli_state *cli,
3240 struct cli_credentials *creds)
3242 struct tevent_context *ev = NULL;
3243 struct tevent_req *req = NULL;
3244 NTSTATUS status = NT_STATUS_NO_MEMORY;
3246 ev = samba_tevent_context_init(talloc_tos());
3250 req = cli_smb1_setup_encryption_send(ev, ev, cli, creds);
3254 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3257 status = cli_smb1_setup_encryption_recv(req);
3264 establishes a connection right up to doing tconX, password specified.
3265 @param output_cli A fully initialised cli structure, non-null only on success
3266 @param dest_host The netbios name of the remote host
3267 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3268 @param port (optional) The destination port (0 for default)
3269 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3270 @param service_type The 'type' of serivice.
3271 @param creds The used user credentials
3274 struct cli_full_connection_creds_state {
3275 struct tevent_context *ev;
3276 const char *service;
3277 const char *service_type;
3278 struct cli_credentials *creds;
3280 struct cli_state *cli;
3283 static int cli_full_connection_creds_state_destructor(
3284 struct cli_full_connection_creds_state *s)
3286 if (s->cli != NULL) {
3287 cli_shutdown(s->cli);
3293 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq);
3294 static void cli_full_connection_creds_sess_start(struct tevent_req *req);
3295 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq);
3296 static void cli_full_connection_creds_tcon_start(struct tevent_req *req);
3297 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq);
3299 struct tevent_req *cli_full_connection_creds_send(
3300 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3301 const char *my_name, const char *dest_host,
3302 const struct sockaddr_storage *dest_ss, int port,
3303 const char *service, const char *service_type,
3304 struct cli_credentials *creds,
3305 int flags, int signing_state)
3307 struct tevent_req *req, *subreq;
3308 struct cli_full_connection_creds_state *state;
3309 enum credentials_use_kerberos krb5_state;
3310 uint32_t gensec_features = 0;
3312 req = tevent_req_create(mem_ctx, &state,
3313 struct cli_full_connection_creds_state);
3317 talloc_set_destructor(state, cli_full_connection_creds_state_destructor);
3319 flags &= ~CLI_FULL_CONNECTION_USE_KERBEROS;
3320 flags &= ~CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
3321 flags &= ~CLI_FULL_CONNECTION_USE_CCACHE;
3322 flags &= ~CLI_FULL_CONNECTION_USE_NT_HASH;
3324 krb5_state = cli_credentials_get_kerberos_state(creds);
3325 switch (krb5_state) {
3326 case CRED_MUST_USE_KERBEROS:
3327 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3328 flags &= ~CLI_FULL_CONNECTION_DONT_SPNEGO;
3330 case CRED_AUTO_USE_KERBEROS:
3331 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3332 flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
3334 case CRED_DONT_USE_KERBEROS:
3338 gensec_features = cli_credentials_get_gensec_features(creds);
3339 if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
3340 flags |= CLI_FULL_CONNECTION_USE_CCACHE;
3344 state->service = service;
3345 state->service_type = service_type;
3346 state->creds = creds;
3347 state->flags = flags;
3349 subreq = cli_start_connection_send(
3350 state, ev, my_name, dest_host, dest_ss, port,
3351 signing_state, flags);
3352 if (tevent_req_nomem(subreq, req)) {
3353 return tevent_req_post(req, ev);
3355 tevent_req_set_callback(subreq,
3356 cli_full_connection_creds_conn_done,
3361 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq)
3363 struct tevent_req *req = tevent_req_callback_data(
3364 subreq, struct tevent_req);
3365 struct cli_full_connection_creds_state *state = tevent_req_data(
3366 req, struct cli_full_connection_creds_state);
3369 status = cli_start_connection_recv(subreq, &state->cli);
3370 TALLOC_FREE(subreq);
3371 if (tevent_req_nterror(req, status)) {
3375 cli_full_connection_creds_sess_start(req);
3378 static void cli_full_connection_creds_sess_start(struct tevent_req *req)
3380 struct cli_full_connection_creds_state *state = tevent_req_data(
3381 req, struct cli_full_connection_creds_state);
3382 struct tevent_req *subreq = NULL;
3384 subreq = cli_session_setup_creds_send(
3385 state, state->ev, state->cli, state->creds);
3386 if (tevent_req_nomem(subreq, req)) {
3389 tevent_req_set_callback(subreq,
3390 cli_full_connection_creds_sess_done,
3394 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq)
3396 struct tevent_req *req = tevent_req_callback_data(
3397 subreq, struct tevent_req);
3398 struct cli_full_connection_creds_state *state = tevent_req_data(
3399 req, struct cli_full_connection_creds_state);
3402 status = cli_session_setup_creds_recv(subreq);
3403 TALLOC_FREE(subreq);
3405 if (!NT_STATUS_IS_OK(status) &&
3406 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3408 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3410 state->creds = cli_credentials_init_anon(state);
3411 if (tevent_req_nomem(state->creds, req)) {
3415 cli_full_connection_creds_sess_start(req);
3419 if (tevent_req_nterror(req, status)) {
3423 cli_full_connection_creds_tcon_start(req);
3426 static void cli_full_connection_creds_tcon_start(struct tevent_req *req)
3428 struct cli_full_connection_creds_state *state = tevent_req_data(
3429 req, struct cli_full_connection_creds_state);
3430 struct tevent_req *subreq = NULL;
3431 const char *password = NULL;
3433 if (state->service == NULL) {
3434 tevent_req_done(req);
3438 password = cli_credentials_get_password(state->creds);
3440 subreq = cli_tree_connect_send(state, state->ev,
3443 state->service_type,
3445 if (tevent_req_nomem(subreq, req)) {
3448 tevent_req_set_callback(subreq,
3449 cli_full_connection_creds_tcon_done,
3453 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq)
3455 struct tevent_req *req = tevent_req_callback_data(
3456 subreq, struct tevent_req);
3459 status = cli_tree_connect_recv(subreq);
3460 TALLOC_FREE(subreq);
3461 if (tevent_req_nterror(req, status)) {
3465 tevent_req_done(req);
3468 NTSTATUS cli_full_connection_creds_recv(struct tevent_req *req,
3469 struct cli_state **output_cli)
3471 struct cli_full_connection_creds_state *state = tevent_req_data(
3472 req, struct cli_full_connection_creds_state);
3475 if (tevent_req_is_nterror(req, &status)) {
3478 *output_cli = state->cli;
3479 talloc_set_destructor(state, NULL);
3480 return NT_STATUS_OK;
3483 NTSTATUS cli_full_connection_creds(struct cli_state **output_cli,
3484 const char *my_name,
3485 const char *dest_host,
3486 const struct sockaddr_storage *dest_ss, int port,
3487 const char *service, const char *service_type,
3488 struct cli_credentials *creds,
3492 struct tevent_context *ev;
3493 struct tevent_req *req;
3494 NTSTATUS status = NT_STATUS_NO_MEMORY;
3496 ev = samba_tevent_context_init(talloc_tos());
3500 req = cli_full_connection_creds_send(
3501 ev, ev, my_name, dest_host, dest_ss, port, service,
3502 service_type, creds, flags, signing_state);
3506 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3509 status = cli_full_connection_creds_recv(req, output_cli);
3515 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3516 const char *my_name,
3517 const char *dest_host,
3518 const struct sockaddr_storage *dest_ss, int port,
3519 const char *service, const char *service_type,
3520 const char *user, const char *domain,
3521 const char *password, int flags,
3524 TALLOC_CTX *frame = talloc_stackframe();
3526 bool use_kerberos = false;
3527 bool fallback_after_kerberos = false;
3528 bool use_ccache = false;
3529 bool pw_nt_hash = false;
3530 struct cli_credentials *creds = NULL;
3532 if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) {
3533 use_kerberos = true;
3536 if (flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) {
3537 fallback_after_kerberos = true;
3540 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
3544 if (flags & CLI_FULL_CONNECTION_USE_NT_HASH) {
3548 creds = cli_session_creds_init(frame,
3551 NULL, /* realm (use default) */
3554 fallback_after_kerberos,
3557 if (creds == NULL) {
3559 return NT_STATUS_NO_MEMORY;
3562 status = cli_full_connection_creds(output_cli, my_name,
3563 dest_host, dest_ss, port,
3564 service, service_type,
3565 creds, flags, signing_state);
3566 if (!NT_STATUS_IS_OK(status)) {
3572 return NT_STATUS_OK;
3575 /****************************************************************************
3576 Send an old style tcon.
3577 ****************************************************************************/
3578 struct cli_raw_tcon_state {
3582 static void cli_raw_tcon_done(struct tevent_req *subreq);
3584 static struct tevent_req *cli_raw_tcon_send(
3585 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3586 const char *service, const char *pass, const char *dev)
3588 struct tevent_req *req, *subreq;
3589 struct cli_raw_tcon_state *state;
3592 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3597 if (!lp_client_plaintext_auth() && (*pass)) {
3598 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3599 " or 'client ntlmv2 auth = yes'\n"));
3600 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3601 return tevent_req_post(req, ev);
3604 bytes = talloc_array(state, uint8_t, 0);
3605 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3606 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3607 service, strlen(service)+1, NULL);
3608 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3609 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3610 pass, strlen(pass)+1, NULL);
3611 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3612 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3613 dev, strlen(dev)+1, NULL);
3615 if (tevent_req_nomem(bytes, req)) {
3616 return tevent_req_post(req, ev);
3619 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3620 talloc_get_size(bytes), bytes);
3621 if (tevent_req_nomem(subreq, req)) {
3622 return tevent_req_post(req, ev);
3624 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3628 static void cli_raw_tcon_done(struct tevent_req *subreq)
3630 struct tevent_req *req = tevent_req_callback_data(
3631 subreq, struct tevent_req);
3632 struct cli_raw_tcon_state *state = tevent_req_data(
3633 req, struct cli_raw_tcon_state);
3636 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3638 TALLOC_FREE(subreq);
3639 if (tevent_req_nterror(req, status)) {
3642 tevent_req_done(req);
3645 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3646 uint16_t *max_xmit, uint16_t *tid)
3648 struct cli_raw_tcon_state *state = tevent_req_data(
3649 req, struct cli_raw_tcon_state);
3652 if (tevent_req_is_nterror(req, &status)) {
3655 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3656 *tid = SVAL(state->ret_vwv + 1, 0);
3657 return NT_STATUS_OK;
3660 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3661 const char *service, const char *pass, const char *dev,
3662 uint16_t *max_xmit, uint16_t *tid)
3664 struct tevent_context *ev;
3665 struct tevent_req *req;
3666 NTSTATUS status = NT_STATUS_NO_MEMORY;
3668 ev = samba_tevent_context_init(talloc_tos());
3672 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3676 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3679 status = cli_raw_tcon_recv(req, max_xmit, tid);
3685 /* Return a cli_state pointing at the IPC$ share for the given server */
3687 struct cli_state *get_ipc_connect(char *server,
3688 struct sockaddr_storage *server_ss,
3689 const struct user_auth_info *user_info)
3691 struct cli_state *cli;
3693 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3695 if (get_cmdline_auth_info_use_kerberos(user_info)) {
3696 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3699 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3700 get_cmdline_auth_info_username(user_info),
3702 get_cmdline_auth_info_password(user_info),
3704 SMB_SIGNING_DEFAULT);
3706 if (NT_STATUS_IS_OK(nt_status)) {
3708 } else if (is_ipaddress(server)) {
3709 /* windows 9* needs a correct NMB name for connections */
3710 fstring remote_name;
3712 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3713 cli = get_ipc_connect(remote_name, server_ss, user_info);
3722 * Given the IP address of a master browser on the network, return its
3723 * workgroup and connect to it.
3725 * This function is provided to allow additional processing beyond what
3726 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3727 * browsers and obtain each master browsers' list of domains (in case the
3728 * first master browser is recently on the network and has not yet
3729 * synchronized with other master browsers and therefore does not yet have the
3730 * entire network browse list)
3733 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3734 struct sockaddr_storage *mb_ip,
3735 const struct user_auth_info *user_info,
3736 char **pp_workgroup_out)
3738 char addr[INET6_ADDRSTRLEN];
3740 struct cli_state *cli;
3741 struct sockaddr_storage server_ss;
3743 *pp_workgroup_out = NULL;
3745 print_sockaddr(addr, sizeof(addr), mb_ip);
3746 DEBUG(99, ("Looking up name of master browser %s\n",
3750 * Do a name status query to find out the name of the master browser.
3751 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3752 * master browser will not respond to a wildcard query (or, at least,
3753 * an NT4 server acting as the domain master browser will not).
3755 * We might be able to use ONLY the query on MSBROWSE, but that's not
3756 * yet been tested with all Windows versions, so until it is, leave
3757 * the original wildcard query as the first choice and fall back to
3758 * MSBROWSE if the wildcard query fails.
3760 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3761 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3763 DEBUG(99, ("Could not retrieve name status for %s\n",
3768 if (!find_master_ip(name, &server_ss)) {
3769 DEBUG(99, ("Could not find master ip for %s\n", name));
3773 *pp_workgroup_out = talloc_strdup(ctx, name);
3775 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3777 print_sockaddr(addr, sizeof(addr), &server_ss);
3778 cli = get_ipc_connect(addr, &server_ss, user_info);
3784 * Return the IP address and workgroup of a master browser on the network, and
3788 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3789 const struct user_auth_info *user_info,
3790 char **pp_workgroup_out)
3792 struct sockaddr_storage *ip_list;
3793 struct cli_state *cli;
3797 *pp_workgroup_out = NULL;
3799 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3801 /* Go looking for workgroups by broadcasting on the local network */
3803 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3805 if (!NT_STATUS_IS_OK(status)) {
3806 DEBUG(99, ("No master browsers responded: %s\n",
3807 nt_errstr(status)));
3811 for (i = 0; i < count; i++) {
3812 char addr[INET6_ADDRSTRLEN];
3813 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3814 DEBUG(99, ("Found master browser %s\n", addr));
3816 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3817 user_info, pp_workgroup_out);