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"
41 #define STAR_SMBSERVER "*SMBSERVER"
43 /********************************************************
44 Utility function to ensure we always return at least
45 a valid char * pointer to an empty string for the
46 cli->server_os, cli->server_type and cli->server_domain
48 *******************************************************/
50 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
57 *destlen = clistr_pull_talloc(mem_ctx,
65 return NT_STATUS_NO_MEMORY;
69 *dest = talloc_strdup(mem_ctx, "");
71 return NT_STATUS_NO_MEMORY;
77 /****************************************************************************
78 Work out suitable capabilities to offer the server.
79 ****************************************************************************/
81 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
82 uint32_t sesssetup_capabilities)
84 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
87 * We only send capabilities based on the mask for:
89 * - flags used in both directions
91 * We do not echo the server only flags, except some legacy flags.
93 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
94 * CAP_LARGE_WRITEX in order to allow us to do large reads
95 * against old Samba releases (<= 3.6.x).
97 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
100 * Session Setup specific flags CAP_DYNAMIC_REAUTH
101 * and CAP_EXTENDED_SECURITY are passed by the caller.
102 * We need that in order to do guest logins even if
103 * CAP_EXTENDED_SECURITY is negotiated.
105 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
106 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
107 client_capabilities |= sesssetup_capabilities;
109 return client_capabilities;
112 /****************************************************************************
113 Do a NT1 guest session setup.
114 ****************************************************************************/
116 struct cli_session_setup_guest_state {
117 struct cli_state *cli;
122 static void cli_session_setup_guest_done(struct tevent_req *subreq);
124 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
125 struct tevent_context *ev,
126 struct cli_state *cli,
127 struct tevent_req **psmbreq)
129 struct tevent_req *req, *subreq;
130 struct cli_session_setup_guest_state *state;
134 req = tevent_req_create(mem_ctx, &state,
135 struct cli_session_setup_guest_state);
142 SCVAL(vwv+0, 0, 0xFF);
145 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
147 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
148 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
153 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
155 bytes = talloc_array(state, uint8_t, 0);
157 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
159 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
161 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
162 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
169 state->bytes.iov_base = (void *)bytes;
170 state->bytes.iov_len = talloc_get_size(bytes);
172 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 0, 13,
173 vwv, 1, &state->bytes);
174 if (subreq == NULL) {
178 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
183 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
184 struct tevent_context *ev,
185 struct cli_state *cli)
187 struct tevent_req *req, *subreq;
190 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
195 status = smb1cli_req_chain_submit(&subreq, 1);
196 if (!NT_STATUS_IS_OK(status)) {
197 tevent_req_nterror(req, status);
198 return tevent_req_post(req, ev);
203 static void cli_session_setup_guest_done(struct tevent_req *subreq)
205 struct tevent_req *req = tevent_req_callback_data(
206 subreq, struct tevent_req);
207 struct cli_session_setup_guest_state *state = tevent_req_data(
208 req, struct cli_session_setup_guest_state);
209 struct cli_state *cli = state->cli;
220 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
223 if (!NT_STATUS_IS_OK(status)) {
224 tevent_req_nterror(req, status);
228 inhdr = in + NBT_HDR_SIZE;
231 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
232 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
234 status = smb_bytes_talloc_string(cli,
241 if (!NT_STATUS_IS_OK(status)) {
242 tevent_req_nterror(req, status);
247 status = smb_bytes_talloc_string(cli,
254 if (!NT_STATUS_IS_OK(status)) {
255 tevent_req_nterror(req, status);
260 status = smb_bytes_talloc_string(cli,
267 if (!NT_STATUS_IS_OK(status)) {
268 tevent_req_nterror(req, status);
273 tevent_req_done(req);
276 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
278 return tevent_req_simple_recv_ntstatus(req);
281 /* The following is calculated from :
283 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
284 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
288 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
290 struct cli_sesssetup_blob_state {
291 struct tevent_context *ev;
292 struct cli_state *cli;
294 uint16_t max_blob_size;
297 struct iovec *recv_iov;
300 const uint8_t *inbuf;
307 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
308 struct tevent_req **psubreq);
309 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
311 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
312 struct tevent_context *ev,
313 struct cli_state *cli,
316 struct tevent_req *req, *subreq;
317 struct cli_sesssetup_blob_state *state;
318 uint32_t usable_space;
320 req = tevent_req_create(mem_ctx, &state,
321 struct cli_sesssetup_blob_state);
329 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
330 usable_space = UINT16_MAX;
332 usable_space = cli_state_available_size(cli,
333 BASE_SESSSETUP_BLOB_PACKET_SIZE);
336 if (usable_space == 0) {
337 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
338 "(not possible to send %u bytes)\n",
339 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
340 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
341 return tevent_req_post(req, ev);
343 state->max_blob_size = MIN(usable_space, 0xFFFF);
345 if (!cli_sesssetup_blob_next(state, &subreq)) {
346 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
347 return tevent_req_post(req, ev);
349 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
353 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
354 struct tevent_req **psubreq)
356 struct tevent_req *subreq;
359 thistime = MIN(state->blob.length, state->max_blob_size);
361 state->this_blob.data = state->blob.data;
362 state->this_blob.length = thistime;
364 state->blob.data += thistime;
365 state->blob.length -= thistime;
367 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
368 subreq = smb2cli_session_setup_send(state, state->ev,
371 state->cli->smb2.session,
373 SMB2_CAP_DFS, /* in_capabilities */
375 0, /* in_previous_session_id */
377 if (subreq == NULL) {
381 uint16_t in_buf_size = 0;
382 uint16_t in_mpx_max = 0;
383 uint16_t in_vc_num = 0;
384 uint32_t in_sess_key = 0;
385 uint32_t in_capabilities = 0;
386 const char *in_native_os = NULL;
387 const char *in_native_lm = NULL;
389 in_buf_size = CLI_BUFFER_SIZE;
390 in_mpx_max = smbXcli_conn_max_requests(state->cli->conn);
391 in_vc_num = cli_state_get_vc_num(state->cli);
392 in_sess_key = smb1cli_conn_server_session_key(state->cli->conn);
393 in_capabilities = cli_session_setup_capabilities(state->cli,
394 CAP_EXTENDED_SECURITY);
395 in_native_os = "Unix";
396 in_native_lm = "Samba";
399 * For now we keep the same values as before,
400 * we may remove these in a separate commit later.
406 subreq = smb1cli_session_setup_ext_send(state, state->ev,
409 state->cli->smb1.pid,
410 state->cli->smb1.session,
419 if (subreq == NULL) {
427 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
429 struct tevent_req *req = tevent_req_callback_data(
430 subreq, struct tevent_req);
431 struct cli_sesssetup_blob_state *state = tevent_req_data(
432 req, struct cli_sesssetup_blob_state);
433 struct cli_state *cli = state->cli;
436 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
437 status = smb2cli_session_setup_recv(subreq, state,
441 status = smb1cli_session_setup_ext_recv(subreq, state,
445 &state->out_native_os,
446 &state->out_native_lm);
449 if (!NT_STATUS_IS_OK(status)
450 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
451 tevent_req_nterror(req, status);
455 if (cli->server_os == NULL) {
456 cli->server_os = talloc_move(cli, &state->out_native_os);
458 if (cli->server_type == NULL) {
459 cli->server_type = talloc_move(cli, &state->out_native_lm);
462 state->status = status;
464 if (state->blob.length != 0) {
468 if (!cli_sesssetup_blob_next(state, &subreq)) {
472 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
475 tevent_req_done(req);
478 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
481 const uint8_t **pinbuf,
482 struct iovec **precv_iov)
484 struct cli_sesssetup_blob_state *state = tevent_req_data(
485 req, struct cli_sesssetup_blob_state);
487 struct iovec *recv_iov;
489 if (tevent_req_is_nterror(req, &status)) {
490 TALLOC_FREE(state->cli->smb2.session);
491 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
492 tevent_req_received(req);
496 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
498 *pblob = state->ret_blob;
500 if (pinbuf != NULL) {
501 *pinbuf = state->inbuf;
503 if (precv_iov != NULL) {
504 *precv_iov = recv_iov;
506 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
507 status = state->status;
508 tevent_req_received(req);
514 /****************************************************************************
515 Use in-memory credentials cache
516 ****************************************************************************/
518 static void use_in_memory_ccache(void) {
519 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
522 #endif /* HAVE_KRB5 */
524 /****************************************************************************
525 Do a spnego/NTLMSSP encrypted session setup.
526 ****************************************************************************/
528 struct cli_session_setup_gensec_state {
529 struct tevent_context *ev;
530 struct cli_state *cli;
531 struct auth_generic_state *auth_generic;
534 const uint8_t *inbuf;
535 struct iovec *recv_iov;
539 DATA_BLOB session_key;
542 static int cli_session_setup_gensec_state_destructor(
543 struct cli_session_setup_gensec_state *state)
545 TALLOC_FREE(state->auth_generic);
546 data_blob_clear_free(&state->session_key);
550 static void cli_session_setup_gensec_local_next(struct tevent_req *req);
551 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
552 static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
553 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
554 static void cli_session_setup_gensec_ready(struct tevent_req *req);
556 static struct tevent_req *cli_session_setup_gensec_send(
557 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
558 const char *user, const char *pass, const char *domain,
559 enum credentials_use_kerberos krb5_state,
560 const char *target_service,
561 const char *target_hostname,
562 const char *target_principal)
564 struct tevent_req *req;
565 struct cli_session_setup_gensec_state *state;
567 const DATA_BLOB *b = NULL;
569 req = tevent_req_create(mem_ctx, &state,
570 struct cli_session_setup_gensec_state);
577 talloc_set_destructor(
578 state, cli_session_setup_gensec_state_destructor);
580 if (user == NULL || strlen(user) == 0) {
581 if (pass != NULL && strlen(pass) == 0) {
583 * some callers pass "" as no password
585 * gensec only handles NULL as no password.
591 status = auth_generic_client_prepare(state, &state->auth_generic);
592 if (tevent_req_nterror(req, status)) {
593 return tevent_req_post(req, ev);
596 gensec_want_feature(state->auth_generic->gensec_security,
597 GENSEC_FEATURE_SESSION_KEY);
598 if (cli->use_ccache) {
599 gensec_want_feature(state->auth_generic->gensec_security,
600 GENSEC_FEATURE_NTLM_CCACHE);
601 if (pass != NULL && strlen(pass) == 0) {
603 * some callers pass "" as no password
605 * GENSEC_FEATURE_NTLM_CCACHE only handles
606 * NULL as no password.
612 status = auth_generic_set_username(state->auth_generic, user);
613 if (tevent_req_nterror(req, status)) {
614 return tevent_req_post(req, ev);
617 status = auth_generic_set_domain(state->auth_generic, domain);
618 if (tevent_req_nterror(req, status)) {
619 return tevent_req_post(req, ev);
622 if (cli->pw_nt_hash) {
623 struct samr_Password nt_hash;
628 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
629 return tevent_req_post(req, ev);
632 converted = strhex_to_str((char *)nt_hash.hash,
633 sizeof(nt_hash.hash),
635 if (converted != sizeof(nt_hash.hash)) {
636 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
637 return tevent_req_post(req, ev);
640 ok = cli_credentials_set_nt_hash(state->auth_generic->credentials,
641 &nt_hash, CRED_SPECIFIED);
644 return tevent_req_post(req, ev);
647 status = auth_generic_set_password(state->auth_generic, pass);
648 if (tevent_req_nterror(req, status)) {
649 return tevent_req_post(req, ev);
653 cli_credentials_set_kerberos_state(state->auth_generic->credentials,
656 if (target_service != NULL) {
657 status = gensec_set_target_service(
658 state->auth_generic->gensec_security,
660 if (tevent_req_nterror(req, status)) {
661 return tevent_req_post(req, ev);
665 if (target_hostname != NULL) {
666 status = gensec_set_target_hostname(
667 state->auth_generic->gensec_security,
669 if (tevent_req_nterror(req, status)) {
670 return tevent_req_post(req, ev);
674 if (target_principal != NULL) {
675 status = gensec_set_target_principal(
676 state->auth_generic->gensec_security,
678 if (tevent_req_nterror(req, status)) {
679 return tevent_req_post(req, ev);
683 b = smbXcli_conn_server_gss_blob(cli->conn);
688 state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
690 status = auth_generic_client_start(state->auth_generic,
692 if (tevent_req_nterror(req, status)) {
693 return tevent_req_post(req, ev);
696 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
697 state->cli->smb2.session = smbXcli_session_create(cli,
699 if (tevent_req_nomem(state->cli->smb2.session, req)) {
700 return tevent_req_post(req, ev);
704 cli_session_setup_gensec_local_next(req);
705 if (!tevent_req_is_in_progress(req)) {
706 return tevent_req_post(req, ev);
712 static void cli_session_setup_gensec_local_next(struct tevent_req *req)
714 struct cli_session_setup_gensec_state *state =
716 struct cli_session_setup_gensec_state);
717 struct tevent_req *subreq = NULL;
719 if (state->local_ready) {
720 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
724 subreq = gensec_update_send(state, state->ev,
725 state->auth_generic->gensec_security,
727 if (tevent_req_nomem(subreq, req)) {
730 tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
733 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
735 struct tevent_req *req =
736 tevent_req_callback_data(subreq,
738 struct cli_session_setup_gensec_state *state =
740 struct cli_session_setup_gensec_state);
743 status = gensec_update_recv(subreq, state, &state->blob_out);
745 state->blob_in = data_blob_null;
746 if (!NT_STATUS_IS_OK(status) &&
747 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
749 tevent_req_nterror(req, status);
753 if (NT_STATUS_IS_OK(status)) {
754 state->local_ready = true;
757 if (state->local_ready && state->remote_ready) {
758 cli_session_setup_gensec_ready(req);
762 cli_session_setup_gensec_remote_next(req);
765 static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
767 struct cli_session_setup_gensec_state *state =
769 struct cli_session_setup_gensec_state);
770 struct tevent_req *subreq = NULL;
772 if (state->remote_ready) {
773 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
777 subreq = cli_sesssetup_blob_send(state, state->ev,
778 state->cli, state->blob_out);
779 if (tevent_req_nomem(subreq, req)) {
782 tevent_req_set_callback(subreq,
783 cli_session_setup_gensec_remote_done,
787 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
789 struct tevent_req *req =
790 tevent_req_callback_data(subreq,
792 struct cli_session_setup_gensec_state *state =
794 struct cli_session_setup_gensec_state);
798 TALLOC_FREE(state->recv_iov);
800 status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
801 &state->inbuf, &state->recv_iov);
803 data_blob_free(&state->blob_out);
804 if (!NT_STATUS_IS_OK(status) &&
805 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
807 tevent_req_nterror(req, status);
811 if (NT_STATUS_IS_OK(status)) {
812 struct smbXcli_session *session = NULL;
813 bool is_guest = false;
815 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
816 session = state->cli->smb2.session;
818 session = state->cli->smb1.session;
821 is_guest = smbXcli_session_is_guest(session);
824 * We can't finish the gensec handshake, we don't
825 * have a negotiated session key.
827 * So just pretend we are completely done.
829 * Note that smbXcli_session_is_guest()
830 * always returns false if we require signing.
832 state->blob_in = data_blob_null;
833 state->local_ready = true;
836 state->remote_ready = true;
839 if (state->local_ready && state->remote_ready) {
840 cli_session_setup_gensec_ready(req);
844 cli_session_setup_gensec_local_next(req);
847 static void cli_session_setup_gensec_ready(struct tevent_req *req)
849 struct cli_session_setup_gensec_state *state =
851 struct cli_session_setup_gensec_state);
852 const char *server_domain = NULL;
855 if (state->blob_in.length != 0) {
856 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
860 if (state->blob_out.length != 0) {
861 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
866 * gensec_ntlmssp_server_domain() returns NULL
867 * if NTLMSSP is not used.
869 * We can remove this later
870 * and leave the server domain empty for SMB2 and above
871 * in future releases.
873 server_domain = gensec_ntlmssp_server_domain(
874 state->auth_generic->gensec_security);
876 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
877 TALLOC_FREE(state->cli->server_domain);
878 state->cli->server_domain = talloc_strdup(state->cli,
880 if (state->cli->server_domain == NULL) {
881 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
886 if (state->is_anonymous) {
888 * Windows server does not set the
889 * SMB2_SESSION_FLAG_IS_NULL flag.
891 * This fix makes sure we do not try
892 * to verify a signature on the final
893 * session setup response.
895 tevent_req_done(req);
899 status = gensec_session_key(state->auth_generic->gensec_security,
900 state, &state->session_key);
901 if (tevent_req_nterror(req, status)) {
905 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
906 struct smbXcli_session *session = state->cli->smb2.session;
908 status = smb2cli_session_set_session_key(session,
911 if (tevent_req_nterror(req, status)) {
915 struct smbXcli_session *session = state->cli->smb1.session;
918 status = smb1cli_session_set_session_key(session,
920 if (tevent_req_nterror(req, status)) {
924 active = smb1cli_conn_activate_signing(state->cli->conn,
930 ok = smb1cli_conn_check_signing(state->cli->conn,
933 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
939 tevent_req_done(req);
942 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
944 struct cli_session_setup_gensec_state *state =
946 struct cli_session_setup_gensec_state);
949 if (tevent_req_is_nterror(req, &status)) {
950 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
958 static char *cli_session_setup_get_principal(
959 TALLOC_CTX *mem_ctx, const char *spnego_principal,
960 const char *remote_name, const char *dest_realm)
962 char *principal = NULL;
964 if (!lp_client_use_spnego_principal() ||
965 strequal(spnego_principal, ADS_IGNORE_PRINCIPAL)) {
966 spnego_principal = NULL;
968 if (spnego_principal != NULL) {
969 DEBUG(3, ("cli_session_setup_spnego: using spnego provided "
970 "principal %s\n", spnego_principal));
971 return talloc_strdup(mem_ctx, spnego_principal);
973 if (is_ipaddress(remote_name) ||
974 strequal(remote_name, STAR_SMBSERVER)) {
978 DEBUG(3, ("cli_session_setup_spnego: using target "
979 "hostname not SPNEGO principal\n"));
982 char *realm = strupper_talloc(talloc_tos(), dest_realm);
986 principal = talloc_asprintf(talloc_tos(), "cifs/%s@%s",
991 smb_krb5_get_principal_from_service_hostname(talloc_tos(),
996 DEBUG(3, ("cli_session_setup_spnego: guessed server principal=%s\n",
997 principal ? principal : "<null>"));
1003 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1004 const char *principal)
1008 account = talloc_strdup(mem_ctx, principal);
1009 if (account == NULL) {
1012 p = strchr_m(account, '@');
1019 /****************************************************************************
1020 Do a spnego encrypted session setup.
1022 user_domain: The shortname of the domain the user/machine is a member of.
1023 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1024 ****************************************************************************/
1026 struct cli_session_setup_spnego_state {
1027 struct tevent_context *ev;
1028 struct cli_state *cli;
1029 const char *target_hostname;
1031 const char *account;
1033 const char *user_domain;
1034 const char *dest_realm;
1039 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq);
1042 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq);
1044 static struct tevent_req *cli_session_setup_spnego_send(
1045 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1046 const char *user, const char *pass, const char *user_domain)
1048 struct tevent_req *req, *subreq;
1049 struct cli_session_setup_spnego_state *state;
1050 char *principal = NULL;
1051 char *OIDs[ASN1_MAX_OIDS];
1053 const char *dest_realm = cli_state_remote_realm(cli);
1054 const DATA_BLOB *server_blob;
1056 req = tevent_req_create(mem_ctx, &state,
1057 struct cli_session_setup_spnego_state);
1065 state->user_domain = user_domain;
1066 state->dest_realm = dest_realm;
1068 state->account = cli_session_setup_get_account(state, user);
1069 if (tevent_req_nomem(state->account, req)) {
1070 return tevent_req_post(req, ev);
1073 state->target_hostname = smbXcli_conn_remote_name(cli->conn);
1074 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1076 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
1077 (unsigned long)server_blob->length));
1079 /* the server might not even do spnego */
1080 if (server_blob->length == 0) {
1081 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1086 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1089 /* The server sent us the first part of the SPNEGO exchange in the
1090 * negprot reply. It is WRONG to depend on the principal sent in the
1091 * negprot reply, but right now we do it. If we don't receive one,
1092 * we try to best guess, then fall back to NTLM. */
1093 if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1094 &principal, NULL) ||
1096 state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1097 tevent_req_done(req);
1098 return tevent_req_post(req, ev);
1101 /* make sure the server understands kerberos */
1102 for (i=0;OIDs[i];i++) {
1104 DEBUG(3,("got OID=%s\n", OIDs[i]));
1106 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1107 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1108 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1109 cli->got_kerberos_mechanism = True;
1111 talloc_free(OIDs[i]);
1114 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1117 /* If password is set we reauthenticate to kerberos server
1118 * and do not store results */
1120 if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
1123 tmp = cli_session_setup_get_principal(
1124 talloc_tos(), principal, state->target_hostname, dest_realm);
1125 TALLOC_FREE(principal);
1128 if (pass && *pass) {
1131 use_in_memory_ccache();
1132 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1135 DEBUG(0, ("Kinit for %s to access %s failed: %s\n", user, principal, error_message(ret)));
1136 TALLOC_FREE(principal);
1137 if (cli->fallback_after_kerberos)
1139 state->result = ADS_ERROR_KRB5(ret);
1140 tevent_req_done(req);
1141 return tevent_req_post(req, ev);
1146 subreq = cli_session_setup_gensec_send(
1148 state->account, pass, user_domain,
1149 CRED_MUST_USE_KERBEROS,
1150 "cifs", state->target_hostname, principal);
1151 if (tevent_req_nomem(subreq, req)) {
1152 return tevent_req_post(req, ev);
1154 tevent_req_set_callback(
1155 subreq, cli_session_setup_spnego_done_krb,
1163 subreq = cli_session_setup_gensec_send(
1164 state, state->ev, state->cli,
1165 state->account, state->pass, state->user_domain,
1166 CRED_DONT_USE_KERBEROS,
1167 "cifs", state->target_hostname, NULL);
1168 if (tevent_req_nomem(subreq, req)) {
1169 return tevent_req_post(req, ev);
1171 tevent_req_set_callback(
1172 subreq, cli_session_setup_spnego_done_ntlmssp, req);
1177 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq)
1179 struct tevent_req *req = tevent_req_callback_data(
1180 subreq, struct tevent_req);
1181 struct cli_session_setup_spnego_state *state = tevent_req_data(
1182 req, struct cli_session_setup_spnego_state);
1185 status = cli_session_setup_gensec_recv(subreq);
1186 TALLOC_FREE(subreq);
1187 state->result = ADS_ERROR_NT(status);
1189 if (ADS_ERR_OK(state->result) ||
1190 !state->cli->fallback_after_kerberos) {
1191 tevent_req_done(req);
1195 subreq = cli_session_setup_gensec_send(
1196 state, state->ev, state->cli,
1197 state->account, state->pass, state->user_domain,
1198 CRED_DONT_USE_KERBEROS,
1199 "cifs", state->target_hostname, NULL);
1200 if (tevent_req_nomem(subreq, req)) {
1203 tevent_req_set_callback(subreq, cli_session_setup_spnego_done_ntlmssp,
1208 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq)
1210 struct tevent_req *req = tevent_req_callback_data(
1211 subreq, struct tevent_req);
1212 struct cli_session_setup_spnego_state *state = tevent_req_data(
1213 req, struct cli_session_setup_spnego_state);
1216 status = cli_session_setup_gensec_recv(subreq);
1217 TALLOC_FREE(subreq);
1218 state->result = ADS_ERROR_NT(status);
1219 tevent_req_done(req);
1222 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1224 struct cli_session_setup_spnego_state *state = tevent_req_data(
1225 req, struct cli_session_setup_spnego_state);
1227 return state->result;
1230 struct cli_session_setup_state {
1231 struct cli_state *cli;
1232 uint8_t nt_hash[16];
1233 uint8_t lm_hash[16];
1234 DATA_BLOB apassword_blob;
1235 DATA_BLOB upassword_blob;
1236 DATA_BLOB lm_session_key;
1237 DATA_BLOB session_key;
1238 char *out_native_os;
1239 char *out_native_lm;
1240 char *out_primary_domain;
1243 static void cli_session_setup_cleanup(struct tevent_req *req,
1244 enum tevent_req_state req_state)
1246 struct cli_session_setup_state *state = tevent_req_data(
1247 req, struct cli_session_setup_state);
1249 if (req_state != TEVENT_REQ_RECEIVED) {
1254 * We only call data_blob_clear() as
1255 * some of the blobs point to the same memory.
1257 * We let the talloc hierachy free the memory.
1259 data_blob_clear(&state->apassword_blob);
1260 data_blob_clear(&state->upassword_blob);
1261 data_blob_clear(&state->lm_session_key);
1262 data_blob_clear(&state->session_key);
1263 ZERO_STRUCTP(state);
1266 static void cli_session_setup_done_spnego(struct tevent_req *subreq);
1267 static void cli_session_setup_done_nt1(struct tevent_req *subreq);
1268 static void cli_session_setup_done_lm21(struct tevent_req *subreq);
1270 /****************************************************************************
1271 Send a session setup. The username and workgroup is in UNIX character
1272 format and must be converted to DOS codepage format before sending. If the
1273 password is in plaintext, the same should be done.
1274 ****************************************************************************/
1276 struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
1277 struct tevent_context *ev,
1278 struct cli_state *cli,
1281 const char *workgroup)
1283 struct tevent_req *req, *subreq;
1284 struct cli_session_setup_state *state;
1287 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1288 bool use_spnego = false;
1289 bool do_lmresponse = false;
1290 const char *username = "";
1291 const char *domain = "";
1292 const char *password = "";
1293 DATA_BLOB target_info = data_blob_null;
1294 DATA_BLOB challenge = data_blob_null;
1295 uint16_t in_buf_size = 0;
1296 uint16_t in_mpx_max = 0;
1297 uint16_t in_vc_num = 0;
1298 uint32_t in_sess_key = 0;
1299 const char *in_native_os = NULL;
1300 const char *in_native_lm = NULL;
1302 req = tevent_req_create(mem_ctx, &state,
1303 struct cli_session_setup_state);
1309 tevent_req_set_cleanup_fn(req, cli_session_setup_cleanup);
1312 user2 = talloc_strdup(state, user);
1314 user2 = talloc_strdup(state, "");
1316 if (user2 == NULL) {
1317 tevent_req_oom(req);
1318 return tevent_req_post(req, ev);
1325 /* allow for workgroups as part of the username */
1326 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1327 (p=strchr_m(user2,*lp_winbind_separator()))) {
1330 if (!strupper_m(user2)) {
1331 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1332 return tevent_req_post(req, ev);
1338 * Now work out what sort of session setup we are going to
1339 * do. I have split this into separate functions to make the flow a bit
1340 * easier to understand (tridge).
1342 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
1344 } else if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1346 } else if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
1348 * if the server supports extended security then use SPNEGO
1349 * even for anonymous connections.
1357 subreq = cli_session_setup_spnego_send(
1358 state, ev, cli, user, pass, workgroup);
1359 if (tevent_req_nomem(subreq, req)) {
1360 return tevent_req_post(req, ev);
1362 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
1367 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1369 * SessionSetupAndX was introduced by LANMAN 1.0. So we skip
1370 * this step against older servers.
1372 tevent_req_done(req);
1373 return tevent_req_post(req, ev);
1376 if (user == NULL || strlen(user) == 0) {
1378 * Do an anonymous session setup
1380 goto non_spnego_creds_done;
1383 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
1385 * Do an anonymous session setup,
1386 * the password is passed via the tree connect.
1388 goto non_spnego_creds_done;
1397 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1398 bool use_unicode = smbXcli_conn_use_unicode(cli->conn);
1399 uint8_t *bytes = NULL;
1400 size_t bytes_len = 0;
1401 const char *pw = password;
1407 pw_len = strlen(pw) + 1;
1409 if (!lp_client_plaintext_auth()) {
1410 DEBUG(1, ("Server requested PLAINTEXT password but "
1411 "'client plaintext auth = no'\n"));
1412 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1413 return tevent_req_post(req, ev);
1416 bytes = talloc_array(state, uint8_t, 0);
1417 bytes = trans2_bytes_push_str(bytes, use_unicode,
1418 pw, pw_len, &bytes_len);
1419 if (tevent_req_nomem(bytes, req)) {
1420 return tevent_req_post(req, ev);
1425 * CAP_UNICODE, can only be negotiated by NT1.
1427 state->upassword_blob = data_blob_const(bytes,
1430 state->apassword_blob = data_blob_const(bytes,
1434 goto non_spnego_creds_done;
1437 challenge = data_blob_const(smb1cli_conn_server_challenge(cli->conn), 8);
1438 E_md4hash(password, state->nt_hash);
1440 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1441 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
1443 * Don't send an NTLMv2 response without NTLMSSP if we
1444 * want to use spnego support.
1446 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
1447 " but 'client use spnego = yes'"
1448 " and 'client ntlmv2 auth = yes' is set\n"));
1449 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1450 return tevent_req_post(req, ev);
1453 if (lp_client_ntlmv2_auth()) {
1457 * note that the 'domain' here is a best
1458 * guess - we don't know the server's domain
1459 * at this point. Windows clients also don't
1462 target_info = NTLMv2_generate_names_blob(state,
1465 if (tevent_req_nomem(target_info.data, req)) {
1466 return tevent_req_post(req, ev);
1469 ok = SMBNTLMv2encrypt_hash(state,
1474 NULL, /* server_timestamp */
1476 &state->apassword_blob,
1477 &state->upassword_blob,
1478 &state->lm_session_key,
1479 &state->session_key);
1481 tevent_req_nterror(req,
1482 NT_STATUS_ACCESS_DENIED);
1483 return tevent_req_post(req, ev);
1486 state->upassword_blob = data_blob_talloc_zero(state, 24);
1487 if (tevent_req_nomem(state->upassword_blob.data, req)) {
1488 return tevent_req_post(req, ev);
1490 state->session_key = data_blob_talloc_zero(state, 16);
1491 if (tevent_req_nomem(state->session_key.data, req)) {
1492 return tevent_req_post(req, ev);
1495 SMBNTencrypt_hash(state->nt_hash, challenge.data,
1496 state->upassword_blob.data);
1497 SMBsesskeygen_ntv1(state->nt_hash,
1498 state->session_key.data);
1500 if (lp_client_lanman_auth()) {
1501 do_lmresponse = E_deshash(password,
1506 if (!lp_client_lanman_auth()) {
1507 DEBUG(1, ("Server requested LM password but "
1508 "'client lanman auth = no' "
1509 "or 'client ntlmv2 auth = yes' is set\n"));
1510 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1511 return tevent_req_post(req, ev);
1514 do_lmresponse = E_deshash(password, state->lm_hash);
1517 if (do_lmresponse) {
1518 state->apassword_blob = data_blob_talloc_zero(state, 24);
1519 if (tevent_req_nomem(state->apassword_blob.data, req)) {
1520 return tevent_req_post(req, ev);
1523 SMBencrypt_hash(state->lm_hash,
1525 state->apassword_blob.data);
1528 if (state->apassword_blob.length == 0) {
1529 if (state->upassword_blob.length == 0) {
1530 DEBUG(1, ("Password is > 14 chars in length, and is "
1531 "therefore incompatible with Lanman "
1532 "authentication\n"));
1533 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1534 return tevent_req_post(req, ev);
1538 * LM disabled, place NT# in LM field
1541 state->apassword_blob = state->upassword_blob;
1544 non_spnego_creds_done:
1546 in_buf_size = CLI_BUFFER_SIZE;
1547 in_mpx_max = smbXcli_conn_max_requests(cli->conn);
1548 in_vc_num = cli_state_get_vc_num(cli);
1549 in_sess_key = smb1cli_conn_server_session_key(cli->conn);
1550 in_native_os = "Unix";
1551 in_native_lm = "Samba";
1553 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1554 uint32_t in_capabilities = 0;
1556 in_capabilities = cli_session_setup_capabilities(cli, 0);
1559 * For now we keep the same values as before,
1560 * we may remove these in a separate commit later.
1564 subreq = smb1cli_session_setup_nt1_send(state, ev,
1575 state->apassword_blob,
1576 state->upassword_blob,
1580 if (tevent_req_nomem(subreq, req)) {
1581 return tevent_req_post(req, ev);
1583 tevent_req_set_callback(subreq, cli_session_setup_done_nt1,
1589 * For now we keep the same values as before,
1590 * we may remove these in a separate commit later.
1595 subreq = smb1cli_session_setup_lm21_send(state, ev,
1606 state->apassword_blob,
1609 if (tevent_req_nomem(subreq, req)) {
1610 return tevent_req_post(req, ev);
1612 tevent_req_set_callback(subreq, cli_session_setup_done_lm21,
1617 static void cli_session_setup_done_spnego(struct tevent_req *subreq)
1619 struct tevent_req *req = tevent_req_callback_data(
1620 subreq, struct tevent_req);
1623 status = cli_session_setup_spnego_recv(subreq);
1624 TALLOC_FREE(subreq);
1625 if (!ADS_ERR_OK(status)) {
1626 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1627 tevent_req_nterror(req, ads_ntstatus(status));
1630 tevent_req_done(req);
1633 static void cli_session_setup_done_nt1(struct tevent_req *subreq)
1635 struct tevent_req *req = tevent_req_callback_data(
1636 subreq, struct tevent_req);
1637 struct cli_session_setup_state *state = tevent_req_data(
1638 req, struct cli_session_setup_state);
1639 struct cli_state *cli = state->cli;
1641 struct iovec *recv_iov = NULL;
1642 const uint8_t *inbuf = NULL;
1645 status = smb1cli_session_setup_nt1_recv(subreq, state,
1648 &state->out_native_os,
1649 &state->out_native_lm,
1650 &state->out_primary_domain);
1651 TALLOC_FREE(subreq);
1652 if (!NT_STATUS_IS_OK(status)) {
1653 DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
1654 tevent_req_nterror(req, status);
1658 if (cli->server_os == NULL) {
1659 cli->server_os = talloc_move(cli, &state->out_native_os);
1661 if (cli->server_type == NULL) {
1662 cli->server_type = talloc_move(cli, &state->out_native_lm);
1664 if (cli->server_domain == NULL) {
1665 cli->server_domain = talloc_move(cli, &state->out_primary_domain);
1668 ok = smb1cli_conn_activate_signing(cli->conn,
1670 state->upassword_blob);
1672 ok = smb1cli_conn_check_signing(cli->conn, inbuf, 1);
1674 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1679 if (state->session_key.data) {
1680 struct smbXcli_session *session = cli->smb1.session;
1682 status = smb1cli_session_set_session_key(session,
1683 state->session_key);
1684 if (tevent_req_nterror(req, status)) {
1689 tevent_req_done(req);
1692 static void cli_session_setup_done_lm21(struct tevent_req *subreq)
1694 struct tevent_req *req = tevent_req_callback_data(
1695 subreq, struct tevent_req);
1696 struct cli_session_setup_state *state = tevent_req_data(
1697 req, struct cli_session_setup_state);
1698 struct cli_state *cli = state->cli;
1701 status = smb1cli_session_setup_lm21_recv(subreq, state,
1702 &state->out_native_os,
1703 &state->out_native_lm);
1704 TALLOC_FREE(subreq);
1705 if (!NT_STATUS_IS_OK(status)) {
1706 DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
1707 tevent_req_nterror(req, status);
1711 if (cli->server_os == NULL) {
1712 cli->server_os = talloc_move(cli, &state->out_native_os);
1714 if (cli->server_type == NULL) {
1715 cli->server_type = talloc_move(cli, &state->out_native_lm);
1718 tevent_req_done(req);
1721 NTSTATUS cli_session_setup_recv(struct tevent_req *req)
1723 return tevent_req_simple_recv_ntstatus(req);
1726 NTSTATUS cli_session_setup(struct cli_state *cli,
1729 const char *workgroup)
1731 struct tevent_context *ev;
1732 struct tevent_req *req;
1733 NTSTATUS status = NT_STATUS_NO_MEMORY;
1735 if (smbXcli_conn_has_async_calls(cli->conn)) {
1736 return NT_STATUS_INVALID_PARAMETER;
1738 ev = samba_tevent_context_init(talloc_tos());
1742 req = cli_session_setup_send(ev, ev, cli, user, pass, workgroup);
1746 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1749 status = cli_session_setup_recv(req);
1755 /****************************************************************************
1757 *****************************************************************************/
1759 struct cli_ulogoff_state {
1760 struct cli_state *cli;
1764 static void cli_ulogoff_done(struct tevent_req *subreq);
1766 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1767 struct tevent_context *ev,
1768 struct cli_state *cli)
1770 struct tevent_req *req, *subreq;
1771 struct cli_ulogoff_state *state;
1773 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1779 SCVAL(state->vwv+0, 0, 0xFF);
1780 SCVAL(state->vwv+1, 0, 0);
1781 SSVAL(state->vwv+2, 0, 0);
1783 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
1785 if (tevent_req_nomem(subreq, req)) {
1786 return tevent_req_post(req, ev);
1788 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1792 static void cli_ulogoff_done(struct tevent_req *subreq)
1794 struct tevent_req *req = tevent_req_callback_data(
1795 subreq, struct tevent_req);
1796 struct cli_ulogoff_state *state = tevent_req_data(
1797 req, struct cli_ulogoff_state);
1800 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1801 if (!NT_STATUS_IS_OK(status)) {
1802 tevent_req_nterror(req, status);
1805 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1806 tevent_req_done(req);
1809 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1811 return tevent_req_simple_recv_ntstatus(req);
1814 NTSTATUS cli_ulogoff(struct cli_state *cli)
1816 struct tevent_context *ev;
1817 struct tevent_req *req;
1818 NTSTATUS status = NT_STATUS_NO_MEMORY;
1820 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1821 status = smb2cli_logoff(cli->conn,
1824 if (!NT_STATUS_IS_OK(status)) {
1827 smb2cli_session_set_id_and_flags(cli->smb2.session,
1829 return NT_STATUS_OK;
1832 if (smbXcli_conn_has_async_calls(cli->conn)) {
1833 return NT_STATUS_INVALID_PARAMETER;
1835 ev = samba_tevent_context_init(talloc_tos());
1839 req = cli_ulogoff_send(ev, ev, cli);
1843 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1846 status = cli_ulogoff_recv(req);
1852 /****************************************************************************
1854 ****************************************************************************/
1856 struct cli_tcon_andx_state {
1857 struct cli_state *cli;
1862 static void cli_tcon_andx_done(struct tevent_req *subreq);
1864 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1865 struct tevent_context *ev,
1866 struct cli_state *cli,
1867 const char *share, const char *dev,
1868 const char *pass, int passlen,
1869 struct tevent_req **psmbreq)
1871 struct tevent_req *req, *subreq;
1872 struct cli_tcon_andx_state *state;
1877 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1878 uint16_t tcon_flags = 0;
1882 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1889 cli->share = talloc_strdup(cli, share);
1894 /* in user level security don't send a password now */
1895 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1898 } else if (pass == NULL) {
1899 DEBUG(1, ("Server not using user level security and no "
1900 "password supplied.\n"));
1904 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1905 *pass && passlen != 24) {
1906 if (!lp_client_lanman_auth()) {
1907 DEBUG(1, ("Server requested LANMAN password "
1908 "(share-level security) but "
1909 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
1914 * Non-encrypted passwords - convert to DOS codepage before
1917 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
1919 pass = (const char *)p24;
1921 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1922 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1926 if (!lp_client_plaintext_auth() && (*pass)) {
1927 DEBUG(1, ("Server requested PLAINTEXT "
1929 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
1934 * Non-encrypted passwords - convert to DOS codepage
1937 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
1938 if (tevent_req_nomem(tmp_pass, req)) {
1939 return tevent_req_post(req, ev);
1941 tmp_pass = trans2_bytes_push_str(tmp_pass,
1942 false, /* always DOS */
1946 if (tevent_req_nomem(tmp_pass, req)) {
1947 return tevent_req_post(req, ev);
1949 pass = (const char *)tmp_pass;
1950 passlen = talloc_get_size(tmp_pass);
1954 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
1955 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
1957 SCVAL(vwv+0, 0, 0xFF);
1960 SSVAL(vwv+2, 0, tcon_flags);
1961 SSVAL(vwv+3, 0, passlen);
1963 if (passlen && pass) {
1964 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
1966 bytes = talloc_array(state, uint8_t, 0);
1972 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1973 smbXcli_conn_remote_name(cli->conn), share);
1978 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
1983 * Add the devicetype
1985 tmp = talloc_strdup_upper(talloc_tos(), dev);
1990 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1993 if (bytes == NULL) {
1998 state->bytes.iov_base = (void *)bytes;
1999 state->bytes.iov_len = talloc_get_size(bytes);
2001 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
2003 if (subreq == NULL) {
2007 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2012 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2013 return tevent_req_post(req, ev);
2016 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2017 struct tevent_context *ev,
2018 struct cli_state *cli,
2019 const char *share, const char *dev,
2020 const char *pass, int passlen)
2022 struct tevent_req *req, *subreq;
2025 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2030 if (subreq == NULL) {
2033 status = smb1cli_req_chain_submit(&subreq, 1);
2034 if (!NT_STATUS_IS_OK(status)) {
2035 tevent_req_nterror(req, status);
2036 return tevent_req_post(req, ev);
2041 static void cli_tcon_andx_done(struct tevent_req *subreq)
2043 struct tevent_req *req = tevent_req_callback_data(
2044 subreq, struct tevent_req);
2045 struct cli_tcon_andx_state *state = tevent_req_data(
2046 req, struct cli_tcon_andx_state);
2047 struct cli_state *cli = state->cli;
2055 uint16_t optional_support = 0;
2057 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2058 &num_bytes, &bytes);
2059 TALLOC_FREE(subreq);
2060 if (!NT_STATUS_IS_OK(status)) {
2061 tevent_req_nterror(req, status);
2065 inhdr = in + NBT_HDR_SIZE;
2068 if (clistr_pull_talloc(cli,
2069 (const char *)inhdr,
2070 SVAL(inhdr, HDR_FLG2),
2074 STR_TERMINATE|STR_ASCII) == -1) {
2075 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2079 cli->dev = talloc_strdup(cli, "");
2080 if (cli->dev == NULL) {
2081 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2086 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2087 /* almost certainly win95 - enable bug fixes */
2092 * Make sure that we have the optional support 16-bit field. WCT > 2.
2093 * Avoids issues when connecting to Win9x boxes sharing files
2096 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2097 optional_support = SVAL(vwv+2, 0);
2100 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2101 smb1cli_session_protect_session_key(cli->smb1.session);
2104 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2105 SVAL(inhdr, HDR_TID),
2107 0, /* maximal_access */
2108 0, /* guest_maximal_access */
2110 NULL); /* fs_type */
2112 tevent_req_done(req);
2115 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2117 return tevent_req_simple_recv_ntstatus(req);
2120 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2121 const char *dev, const char *pass, int passlen)
2123 TALLOC_CTX *frame = talloc_stackframe();
2124 struct tevent_context *ev;
2125 struct tevent_req *req;
2126 NTSTATUS status = NT_STATUS_NO_MEMORY;
2128 if (smbXcli_conn_has_async_calls(cli->conn)) {
2130 * Can't use sync call while an async call is in flight
2132 status = NT_STATUS_INVALID_PARAMETER;
2136 ev = samba_tevent_context_init(frame);
2141 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2146 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2150 status = cli_tcon_andx_recv(req);
2156 struct cli_tree_connect_state {
2157 struct cli_state *cli;
2160 static struct tevent_req *cli_raw_tcon_send(
2161 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2162 const char *service, const char *pass, const char *dev);
2163 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2164 uint16_t *max_xmit, uint16_t *tid);
2166 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2167 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2168 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2170 static struct tevent_req *cli_tree_connect_send(
2171 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2172 const char *share, const char *dev, const char *pass, int passlen)
2174 struct tevent_req *req, *subreq;
2175 struct cli_tree_connect_state *state;
2177 req = tevent_req_create(mem_ctx, &state,
2178 struct cli_tree_connect_state);
2184 cli->share = talloc_strdup(cli, share);
2185 if (tevent_req_nomem(cli->share, req)) {
2186 return tevent_req_post(req, ev);
2189 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2192 cli->smb2.tcon = smbXcli_tcon_create(cli);
2193 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2194 return tevent_req_post(req, ev);
2197 unc = talloc_asprintf(state, "\\\\%s\\%s",
2198 smbXcli_conn_remote_name(cli->conn),
2200 if (tevent_req_nomem(unc, req)) {
2201 return tevent_req_post(req, ev);
2204 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2205 cli->smb2.session, cli->smb2.tcon,
2208 if (tevent_req_nomem(subreq, req)) {
2209 return tevent_req_post(req, ev);
2211 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2216 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2217 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2219 if (tevent_req_nomem(subreq, req)) {
2220 return tevent_req_post(req, ev);
2222 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2227 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2228 if (tevent_req_nomem(subreq, req)) {
2229 return tevent_req_post(req, ev);
2231 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2236 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2238 tevent_req_simple_finish_ntstatus(
2239 subreq, smb2cli_tcon_recv(subreq));
2242 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2244 tevent_req_simple_finish_ntstatus(
2245 subreq, cli_tcon_andx_recv(subreq));
2248 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2250 struct tevent_req *req = tevent_req_callback_data(
2251 subreq, struct tevent_req);
2252 struct cli_tree_connect_state *state = tevent_req_data(
2253 req, struct cli_tree_connect_state);
2255 uint16_t max_xmit = 0;
2258 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2259 if (tevent_req_nterror(req, status)) {
2263 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2265 0, /* optional_support */
2266 0, /* maximal_access */
2267 0, /* guest_maximal_access */
2269 NULL); /* fs_type */
2271 tevent_req_done(req);
2274 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2276 return tevent_req_simple_recv_ntstatus(req);
2279 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2280 const char *dev, const char *pass, int passlen)
2282 struct tevent_context *ev;
2283 struct tevent_req *req;
2284 NTSTATUS status = NT_STATUS_NO_MEMORY;
2286 if (smbXcli_conn_has_async_calls(cli->conn)) {
2287 return NT_STATUS_INVALID_PARAMETER;
2289 ev = samba_tevent_context_init(talloc_tos());
2293 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2297 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2300 status = cli_tree_connect_recv(req);
2306 /****************************************************************************
2307 Send a tree disconnect.
2308 ****************************************************************************/
2310 struct cli_tdis_state {
2311 struct cli_state *cli;
2314 static void cli_tdis_done(struct tevent_req *subreq);
2316 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2317 struct tevent_context *ev,
2318 struct cli_state *cli)
2320 struct tevent_req *req, *subreq;
2321 struct cli_tdis_state *state;
2323 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2329 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2330 if (tevent_req_nomem(subreq, req)) {
2331 return tevent_req_post(req, ev);
2333 tevent_req_set_callback(subreq, cli_tdis_done, req);
2337 static void cli_tdis_done(struct tevent_req *subreq)
2339 struct tevent_req *req = tevent_req_callback_data(
2340 subreq, struct tevent_req);
2341 struct cli_tdis_state *state = tevent_req_data(
2342 req, struct cli_tdis_state);
2345 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2346 TALLOC_FREE(subreq);
2347 if (!NT_STATUS_IS_OK(status)) {
2348 tevent_req_nterror(req, status);
2351 cli_state_set_tid(state->cli, UINT16_MAX);
2352 tevent_req_done(req);
2355 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2357 return tevent_req_simple_recv_ntstatus(req);
2360 NTSTATUS cli_tdis(struct cli_state *cli)
2362 struct tevent_context *ev;
2363 struct tevent_req *req;
2364 NTSTATUS status = NT_STATUS_NO_MEMORY;
2366 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2367 return smb2cli_tdis(cli->conn,
2373 if (smbXcli_conn_has_async_calls(cli->conn)) {
2374 return NT_STATUS_INVALID_PARAMETER;
2376 ev = samba_tevent_context_init(talloc_tos());
2380 req = cli_tdis_send(ev, ev, cli);
2384 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2387 status = cli_tdis_recv(req);
2393 struct cli_connect_sock_state {
2394 const char **called_names;
2395 const char **calling_names;
2401 static void cli_connect_sock_done(struct tevent_req *subreq);
2404 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2408 static struct tevent_req *cli_connect_sock_send(
2409 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2410 const char *host, int name_type, const struct sockaddr_storage *pss,
2411 const char *myname, uint16_t port)
2413 struct tevent_req *req, *subreq;
2414 struct cli_connect_sock_state *state;
2416 struct sockaddr_storage *addrs;
2417 unsigned i, num_addrs;
2420 req = tevent_req_create(mem_ctx, &state,
2421 struct cli_connect_sock_state);
2426 prog = getenv("LIBSMB_PROG");
2428 state->fd = sock_exec(prog);
2429 if (state->fd == -1) {
2430 status = map_nt_error_from_unix(errno);
2431 tevent_req_nterror(req, status);
2434 tevent_req_done(req);
2436 return tevent_req_post(req, ev);
2439 if ((pss == NULL) || is_zero_addr(pss)) {
2442 * Here we cheat. resolve_name_list is not async at all. So
2443 * this call will only be really async if the name lookup has
2444 * been done externally.
2447 status = resolve_name_list(state, host, name_type,
2448 &addrs, &num_addrs);
2449 if (!NT_STATUS_IS_OK(status)) {
2450 tevent_req_nterror(req, status);
2451 return tevent_req_post(req, ev);
2454 addrs = talloc_array(state, struct sockaddr_storage, 1);
2455 if (tevent_req_nomem(addrs, req)) {
2456 return tevent_req_post(req, ev);
2462 state->called_names = talloc_array(state, const char *, num_addrs);
2463 if (tevent_req_nomem(state->called_names, req)) {
2464 return tevent_req_post(req, ev);
2466 state->called_types = talloc_array(state, int, num_addrs);
2467 if (tevent_req_nomem(state->called_types, req)) {
2468 return tevent_req_post(req, ev);
2470 state->calling_names = talloc_array(state, const char *, num_addrs);
2471 if (tevent_req_nomem(state->calling_names, req)) {
2472 return tevent_req_post(req, ev);
2474 for (i=0; i<num_addrs; i++) {
2475 state->called_names[i] = host;
2476 state->called_types[i] = name_type;
2477 state->calling_names[i] = myname;
2480 subreq = smbsock_any_connect_send(
2481 state, ev, addrs, state->called_names, state->called_types,
2482 state->calling_names, NULL, num_addrs, port);
2483 if (tevent_req_nomem(subreq, req)) {
2484 return tevent_req_post(req, ev);
2486 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2490 static void cli_connect_sock_done(struct tevent_req *subreq)
2492 struct tevent_req *req = tevent_req_callback_data(
2493 subreq, struct tevent_req);
2494 struct cli_connect_sock_state *state = tevent_req_data(
2495 req, struct cli_connect_sock_state);
2498 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2500 TALLOC_FREE(subreq);
2501 if (tevent_req_nterror(req, status)) {
2504 set_socket_options(state->fd, lp_socket_options());
2505 tevent_req_done(req);
2508 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2509 int *pfd, uint16_t *pport)
2511 struct cli_connect_sock_state *state = tevent_req_data(
2512 req, struct cli_connect_sock_state);
2515 if (tevent_req_is_nterror(req, &status)) {
2519 *pport = state->port;
2520 return NT_STATUS_OK;
2523 struct cli_connect_nb_state {
2524 const char *desthost;
2527 struct cli_state *cli;
2530 static void cli_connect_nb_done(struct tevent_req *subreq);
2532 static struct tevent_req *cli_connect_nb_send(
2533 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2534 const char *host, const struct sockaddr_storage *dest_ss,
2535 uint16_t port, int name_type, const char *myname,
2536 int signing_state, int flags)
2538 struct tevent_req *req, *subreq;
2539 struct cli_connect_nb_state *state;
2541 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2545 state->signing_state = signing_state;
2546 state->flags = flags;
2549 char *p = strchr(host, '#');
2552 name_type = strtol(p+1, NULL, 16);
2553 host = talloc_strndup(state, host, p - host);
2554 if (tevent_req_nomem(host, req)) {
2555 return tevent_req_post(req, ev);
2559 state->desthost = host;
2560 } else if (dest_ss != NULL) {
2561 state->desthost = print_canonical_sockaddr(state, dest_ss);
2562 if (tevent_req_nomem(state->desthost, req)) {
2563 return tevent_req_post(req, ev);
2566 /* No host or dest_ss given. Error out. */
2567 tevent_req_error(req, EINVAL);
2568 return tevent_req_post(req, ev);
2571 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2573 if (tevent_req_nomem(subreq, req)) {
2574 return tevent_req_post(req, ev);
2576 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2580 static void cli_connect_nb_done(struct tevent_req *subreq)
2582 struct tevent_req *req = tevent_req_callback_data(
2583 subreq, struct tevent_req);
2584 struct cli_connect_nb_state *state = tevent_req_data(
2585 req, struct cli_connect_nb_state);
2590 status = cli_connect_sock_recv(subreq, &fd, &port);
2591 TALLOC_FREE(subreq);
2592 if (tevent_req_nterror(req, status)) {
2596 state->cli = cli_state_create(state, fd, state->desthost, NULL,
2597 state->signing_state, state->flags);
2598 if (tevent_req_nomem(state->cli, req)) {
2602 tevent_req_done(req);
2605 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
2606 struct cli_state **pcli)
2608 struct cli_connect_nb_state *state = tevent_req_data(
2609 req, struct cli_connect_nb_state);
2612 if (tevent_req_is_nterror(req, &status)) {
2615 *pcli = talloc_move(NULL, &state->cli);
2616 return NT_STATUS_OK;
2619 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2620 uint16_t port, int name_type, const char *myname,
2621 int signing_state, int flags, struct cli_state **pcli)
2623 struct tevent_context *ev;
2624 struct tevent_req *req;
2625 NTSTATUS status = NT_STATUS_NO_MEMORY;
2627 ev = samba_tevent_context_init(talloc_tos());
2631 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
2632 myname, signing_state, flags);
2636 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
2639 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2642 status = cli_connect_nb_recv(req, pcli);
2648 struct cli_start_connection_state {
2649 struct tevent_context *ev;
2650 struct cli_state *cli;
2655 static void cli_start_connection_connected(struct tevent_req *subreq);
2656 static void cli_start_connection_done(struct tevent_req *subreq);
2659 establishes a connection to after the negprot.
2660 @param output_cli A fully initialised cli structure, non-null only on success
2661 @param dest_host The netbios name of the remote host
2662 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2663 @param port (optional) The destination port (0 for default)
2666 static struct tevent_req *cli_start_connection_send(
2667 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2668 const char *my_name, const char *dest_host,
2669 const struct sockaddr_storage *dest_ss, int port,
2670 int signing_state, int flags)
2672 struct tevent_req *req, *subreq;
2673 struct cli_start_connection_state *state;
2675 req = tevent_req_create(mem_ctx, &state,
2676 struct cli_start_connection_state);
2682 if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
2683 state->min_protocol = lp_client_ipc_min_protocol();
2684 state->max_protocol = lp_client_ipc_max_protocol();
2686 state->min_protocol = lp_client_min_protocol();
2687 state->max_protocol = lp_client_max_protocol();
2690 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
2691 0x20, my_name, signing_state, flags);
2692 if (tevent_req_nomem(subreq, req)) {
2693 return tevent_req_post(req, ev);
2695 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
2699 static void cli_start_connection_connected(struct tevent_req *subreq)
2701 struct tevent_req *req = tevent_req_callback_data(
2702 subreq, struct tevent_req);
2703 struct cli_start_connection_state *state = tevent_req_data(
2704 req, struct cli_start_connection_state);
2707 status = cli_connect_nb_recv(subreq, &state->cli);
2708 TALLOC_FREE(subreq);
2709 if (tevent_req_nterror(req, status)) {
2713 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
2714 state->cli->timeout,
2715 state->min_protocol,
2716 state->max_protocol);
2717 if (tevent_req_nomem(subreq, req)) {
2720 tevent_req_set_callback(subreq, cli_start_connection_done, req);
2723 static void cli_start_connection_done(struct tevent_req *subreq)
2725 struct tevent_req *req = tevent_req_callback_data(
2726 subreq, struct tevent_req);
2727 struct cli_start_connection_state *state = tevent_req_data(
2728 req, struct cli_start_connection_state);
2731 status = smbXcli_negprot_recv(subreq);
2732 TALLOC_FREE(subreq);
2733 if (tevent_req_nterror(req, status)) {
2737 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
2738 /* Ensure we ask for some initial credits. */
2739 smb2cli_conn_set_max_credits(state->cli->conn,
2740 DEFAULT_SMB2_MAX_CREDITS);
2743 tevent_req_done(req);
2746 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
2747 struct cli_state **output_cli)
2749 struct cli_start_connection_state *state = tevent_req_data(
2750 req, struct cli_start_connection_state);
2753 if (tevent_req_is_nterror(req, &status)) {
2756 *output_cli = state->cli;
2758 return NT_STATUS_OK;
2761 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2762 const char *my_name,
2763 const char *dest_host,
2764 const struct sockaddr_storage *dest_ss, int port,
2765 int signing_state, int flags)
2767 struct tevent_context *ev;
2768 struct tevent_req *req;
2769 NTSTATUS status = NT_STATUS_NO_MEMORY;
2771 ev = samba_tevent_context_init(talloc_tos());
2775 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
2776 port, signing_state, flags);
2780 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2783 status = cli_start_connection_recv(req, output_cli);
2790 establishes a connection right up to doing tconX, password specified.
2791 @param output_cli A fully initialised cli structure, non-null only on success
2792 @param dest_host The netbios name of the remote host
2793 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2794 @param port (optional) The destination port (0 for default)
2795 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2796 @param service_type The 'type' of serivice.
2797 @param user Username, unix string
2798 @param domain User's domain
2799 @param password User's password, unencrypted unix string.
2802 struct cli_full_connection_state {
2803 struct tevent_context *ev;
2804 const char *service;
2805 const char *service_type;
2808 const char *password;
2811 struct cli_state *cli;
2814 static int cli_full_connection_state_destructor(
2815 struct cli_full_connection_state *s);
2816 static void cli_full_connection_started(struct tevent_req *subreq);
2817 static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
2818 static void cli_full_connection_done(struct tevent_req *subreq);
2820 struct tevent_req *cli_full_connection_send(
2821 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2822 const char *my_name, const char *dest_host,
2823 const struct sockaddr_storage *dest_ss, int port,
2824 const char *service, const char *service_type,
2825 const char *user, const char *domain,
2826 const char *password, int flags, int signing_state)
2828 struct tevent_req *req, *subreq;
2829 struct cli_full_connection_state *state;
2831 req = tevent_req_create(mem_ctx, &state,
2832 struct cli_full_connection_state);
2836 talloc_set_destructor(state, cli_full_connection_state_destructor);
2839 state->service = service;
2840 state->service_type = service_type;
2842 state->domain = domain;
2843 state->password = password;
2844 state->flags = flags;
2846 state->pw_len = state->password ? strlen(state->password)+1 : 0;
2847 if (state->password == NULL) {
2848 state->password = "";
2851 subreq = cli_start_connection_send(
2852 state, ev, my_name, dest_host, dest_ss, port,
2853 signing_state, flags);
2854 if (tevent_req_nomem(subreq, req)) {
2855 return tevent_req_post(req, ev);
2857 tevent_req_set_callback(subreq, cli_full_connection_started, req);
2861 static int cli_full_connection_state_destructor(
2862 struct cli_full_connection_state *s)
2864 if (s->cli != NULL) {
2865 cli_shutdown(s->cli);
2871 static void cli_full_connection_started(struct tevent_req *subreq)
2873 struct tevent_req *req = tevent_req_callback_data(
2874 subreq, struct tevent_req);
2875 struct cli_full_connection_state *state = tevent_req_data(
2876 req, struct cli_full_connection_state);
2879 status = cli_start_connection_recv(subreq, &state->cli);
2880 TALLOC_FREE(subreq);
2881 if (tevent_req_nterror(req, status)) {
2884 subreq = cli_session_setup_send(
2885 state, state->ev, state->cli, state->user,
2886 state->password, state->domain);
2887 if (tevent_req_nomem(subreq, req)) {
2890 tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
2893 static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
2895 struct tevent_req *req = tevent_req_callback_data(
2896 subreq, struct tevent_req);
2897 struct cli_full_connection_state *state = tevent_req_data(
2898 req, struct cli_full_connection_state);
2901 status = cli_session_setup_recv(subreq);
2902 TALLOC_FREE(subreq);
2904 if (!NT_STATUS_IS_OK(status) &&
2905 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2907 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2909 subreq = cli_session_setup_send(
2910 state, state->ev, state->cli, "", "",
2912 if (tevent_req_nomem(subreq, req)) {
2915 tevent_req_set_callback(
2916 subreq, cli_full_connection_sess_set_up, req);
2920 if (tevent_req_nterror(req, status)) {
2924 if (state->service != NULL) {
2925 subreq = cli_tree_connect_send(
2926 state, state->ev, state->cli,
2927 state->service, state->service_type,
2928 state->password, state->pw_len);
2929 if (tevent_req_nomem(subreq, req)) {
2932 tevent_req_set_callback(subreq, cli_full_connection_done, req);
2936 tevent_req_done(req);
2939 static void cli_full_connection_done(struct tevent_req *subreq)
2941 struct tevent_req *req = tevent_req_callback_data(
2942 subreq, struct tevent_req);
2945 status = cli_tree_connect_recv(subreq);
2946 TALLOC_FREE(subreq);
2947 if (tevent_req_nterror(req, status)) {
2951 tevent_req_done(req);
2954 NTSTATUS cli_full_connection_recv(struct tevent_req *req,
2955 struct cli_state **output_cli)
2957 struct cli_full_connection_state *state = tevent_req_data(
2958 req, struct cli_full_connection_state);
2961 if (tevent_req_is_nterror(req, &status)) {
2964 *output_cli = state->cli;
2965 talloc_set_destructor(state, NULL);
2966 return NT_STATUS_OK;
2969 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2970 const char *my_name,
2971 const char *dest_host,
2972 const struct sockaddr_storage *dest_ss, int port,
2973 const char *service, const char *service_type,
2974 const char *user, const char *domain,
2975 const char *password, int flags,
2978 struct tevent_context *ev;
2979 struct tevent_req *req;
2980 NTSTATUS status = NT_STATUS_NO_MEMORY;
2982 ev = samba_tevent_context_init(talloc_tos());
2986 req = cli_full_connection_send(
2987 ev, ev, my_name, dest_host, dest_ss, port, service,
2988 service_type, user, domain, password, flags, signing_state);
2992 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2995 status = cli_full_connection_recv(req, output_cli);
3001 /****************************************************************************
3002 Send an old style tcon.
3003 ****************************************************************************/
3004 struct cli_raw_tcon_state {
3008 static void cli_raw_tcon_done(struct tevent_req *subreq);
3010 static struct tevent_req *cli_raw_tcon_send(
3011 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3012 const char *service, const char *pass, const char *dev)
3014 struct tevent_req *req, *subreq;
3015 struct cli_raw_tcon_state *state;
3018 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3023 if (!lp_client_plaintext_auth() && (*pass)) {
3024 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3025 " or 'client ntlmv2 auth = yes'\n"));
3026 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3027 return tevent_req_post(req, ev);
3030 bytes = talloc_array(state, uint8_t, 0);
3031 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3032 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3033 service, strlen(service)+1, NULL);
3034 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3035 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3036 pass, strlen(pass)+1, NULL);
3037 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3038 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3039 dev, strlen(dev)+1, NULL);
3041 if (tevent_req_nomem(bytes, req)) {
3042 return tevent_req_post(req, ev);
3045 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3046 talloc_get_size(bytes), bytes);
3047 if (tevent_req_nomem(subreq, req)) {
3048 return tevent_req_post(req, ev);
3050 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3054 static void cli_raw_tcon_done(struct tevent_req *subreq)
3056 struct tevent_req *req = tevent_req_callback_data(
3057 subreq, struct tevent_req);
3058 struct cli_raw_tcon_state *state = tevent_req_data(
3059 req, struct cli_raw_tcon_state);
3062 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3064 TALLOC_FREE(subreq);
3065 if (tevent_req_nterror(req, status)) {
3068 tevent_req_done(req);
3071 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3072 uint16_t *max_xmit, uint16_t *tid)
3074 struct cli_raw_tcon_state *state = tevent_req_data(
3075 req, struct cli_raw_tcon_state);
3078 if (tevent_req_is_nterror(req, &status)) {
3081 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3082 *tid = SVAL(state->ret_vwv + 1, 0);
3083 return NT_STATUS_OK;
3086 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3087 const char *service, const char *pass, const char *dev,
3088 uint16_t *max_xmit, uint16_t *tid)
3090 struct tevent_context *ev;
3091 struct tevent_req *req;
3092 NTSTATUS status = NT_STATUS_NO_MEMORY;
3094 ev = samba_tevent_context_init(talloc_tos());
3098 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3102 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3105 status = cli_raw_tcon_recv(req, max_xmit, tid);
3111 /* Return a cli_state pointing at the IPC$ share for the given server */
3113 struct cli_state *get_ipc_connect(char *server,
3114 struct sockaddr_storage *server_ss,
3115 const struct user_auth_info *user_info)
3117 struct cli_state *cli;
3119 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3121 if (get_cmdline_auth_info_use_kerberos(user_info)) {
3122 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3125 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3126 get_cmdline_auth_info_username(user_info),
3128 get_cmdline_auth_info_password(user_info),
3130 SMB_SIGNING_DEFAULT);
3132 if (NT_STATUS_IS_OK(nt_status)) {
3134 } else if (is_ipaddress(server)) {
3135 /* windows 9* needs a correct NMB name for connections */
3136 fstring remote_name;
3138 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3139 cli = get_ipc_connect(remote_name, server_ss, user_info);
3148 * Given the IP address of a master browser on the network, return its
3149 * workgroup and connect to it.
3151 * This function is provided to allow additional processing beyond what
3152 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3153 * browsers and obtain each master browsers' list of domains (in case the
3154 * first master browser is recently on the network and has not yet
3155 * synchronized with other master browsers and therefore does not yet have the
3156 * entire network browse list)
3159 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3160 struct sockaddr_storage *mb_ip,
3161 const struct user_auth_info *user_info,
3162 char **pp_workgroup_out)
3164 char addr[INET6_ADDRSTRLEN];
3166 struct cli_state *cli;
3167 struct sockaddr_storage server_ss;
3169 *pp_workgroup_out = NULL;
3171 print_sockaddr(addr, sizeof(addr), mb_ip);
3172 DEBUG(99, ("Looking up name of master browser %s\n",
3176 * Do a name status query to find out the name of the master browser.
3177 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3178 * master browser will not respond to a wildcard query (or, at least,
3179 * an NT4 server acting as the domain master browser will not).
3181 * We might be able to use ONLY the query on MSBROWSE, but that's not
3182 * yet been tested with all Windows versions, so until it is, leave
3183 * the original wildcard query as the first choice and fall back to
3184 * MSBROWSE if the wildcard query fails.
3186 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3187 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3189 DEBUG(99, ("Could not retrieve name status for %s\n",
3194 if (!find_master_ip(name, &server_ss)) {
3195 DEBUG(99, ("Could not find master ip for %s\n", name));
3199 *pp_workgroup_out = talloc_strdup(ctx, name);
3201 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3203 print_sockaddr(addr, sizeof(addr), &server_ss);
3204 cli = get_ipc_connect(addr, &server_ss, user_info);
3210 * Return the IP address and workgroup of a master browser on the network, and
3214 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3215 const struct user_auth_info *user_info,
3216 char **pp_workgroup_out)
3218 struct sockaddr_storage *ip_list;
3219 struct cli_state *cli;
3223 *pp_workgroup_out = NULL;
3225 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3227 /* Go looking for workgroups by broadcasting on the local network */
3229 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3231 if (!NT_STATUS_IS_OK(status)) {
3232 DEBUG(99, ("No master browsers responded: %s\n",
3233 nt_errstr(status)));
3237 for (i = 0; i < count; i++) {
3238 char addr[INET6_ADDRSTRLEN];
3239 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3240 DEBUG(99, ("Found master browser %s\n", addr));
3242 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3243 user_info, pp_workgroup_out);