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/ntlmssp/ntlmssp.h"
30 #include "libads/kerberos_proto.h"
32 #include "../lib/util/tevent_ntstatus.h"
33 #include "async_smb.h"
34 #include "libsmb/nmblib.h"
35 #include "librpc/ndr/libndr.h"
36 #include "../libcli/smb/smbXcli_base.h"
39 #define STAR_SMBSERVER "*SMBSERVER"
41 /********************************************************
42 Utility function to ensure we always return at least
43 a valid char * pointer to an empty string for the
44 cli->server_os, cli->server_type and cli->server_domain
46 *******************************************************/
48 static NTSTATUS
smb_bytes_talloc_string(TALLOC_CTX
*mem_ctx
,
55 *destlen
= clistr_pull_talloc(mem_ctx
,
63 return NT_STATUS_NO_MEMORY
;
67 *dest
= talloc_strdup(mem_ctx
, "");
69 return NT_STATUS_NO_MEMORY
;
75 /****************************************************************************
76 Do an old lanman2 style session setup.
77 ****************************************************************************/
79 struct cli_session_setup_lanman2_state
{
80 struct cli_state
*cli
;
85 static void cli_session_setup_lanman2_done(struct tevent_req
*subreq
);
87 static struct tevent_req
*cli_session_setup_lanman2_send(
88 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
89 struct cli_state
*cli
, const char *user
,
90 const char *pass
, size_t passlen
,
91 const char *workgroup
)
93 struct tevent_req
*req
, *subreq
;
94 struct cli_session_setup_lanman2_state
*state
;
95 DATA_BLOB lm_response
= data_blob_null
;
99 uint16_t sec_mode
= smb1cli_conn_server_security_mode(cli
->conn
);
101 req
= tevent_req_create(mem_ctx
, &state
,
102 struct cli_session_setup_lanman2_state
);
111 * if in share level security then don't send a password now
113 if (!(sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
)) {
118 && (sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
)
121 * Encrypted mode needed, and non encrypted password
124 lm_response
= data_blob(NULL
, 24);
125 if (tevent_req_nomem(lm_response
.data
, req
)) {
126 return tevent_req_post(req
, ev
);
129 if (!SMBencrypt(pass
, smb1cli_conn_server_challenge(cli
->conn
),
130 (uint8_t *)lm_response
.data
)) {
131 DEBUG(1, ("Password is > 14 chars in length, and is "
132 "therefore incompatible with Lanman "
133 "authentication\n"));
134 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
135 return tevent_req_post(req
, ev
);
137 } else if ((sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
)
140 * Encrypted mode needed, and encrypted password
143 lm_response
= data_blob(pass
, passlen
);
144 if (tevent_req_nomem(lm_response
.data
, req
)) {
145 return tevent_req_post(req
, ev
);
147 } else if (passlen
> 0) {
149 size_t converted_size
;
151 * Plaintext mode needed, assume plaintext supplied.
153 buf
= talloc_array(talloc_tos(), uint8_t, 0);
154 buf
= smb_bytes_push_str(buf
, smbXcli_conn_use_unicode(cli
->conn
), pass
, passlen
+1,
156 if (tevent_req_nomem(buf
, req
)) {
157 return tevent_req_post(req
, ev
);
159 lm_response
= data_blob(pass
, passlen
);
161 if (tevent_req_nomem(lm_response
.data
, req
)) {
162 return tevent_req_post(req
, ev
);
166 SCVAL(vwv
+0, 0, 0xff);
169 SSVAL(vwv
+2, 0, CLI_BUFFER_SIZE
);
172 SIVAL(vwv
+5, 0, smb1cli_conn_server_session_key(cli
->conn
));
173 SSVAL(vwv
+7, 0, lm_response
.length
);
175 bytes
= talloc_array(state
, uint8_t, lm_response
.length
);
176 if (tevent_req_nomem(bytes
, req
)) {
177 return tevent_req_post(req
, ev
);
179 if (lm_response
.length
!= 0) {
180 memcpy(bytes
, lm_response
.data
, lm_response
.length
);
182 data_blob_free(&lm_response
);
184 tmp
= talloc_strdup_upper(talloc_tos(), user
);
185 if (tevent_req_nomem(tmp
, req
)) {
186 return tevent_req_post(req
, ev
);
188 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), tmp
, strlen(tmp
)+1,
192 tmp
= talloc_strdup_upper(talloc_tos(), workgroup
);
193 if (tevent_req_nomem(tmp
, req
)) {
194 return tevent_req_post(req
, ev
);
196 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), tmp
, strlen(tmp
)+1,
198 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "Unix", 5, NULL
);
199 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "Samba", 6, NULL
);
201 if (tevent_req_nomem(bytes
, req
)) {
202 return tevent_req_post(req
, ev
);
205 subreq
= cli_smb_send(state
, ev
, cli
, SMBsesssetupX
, 0, 10, vwv
,
206 talloc_get_size(bytes
), bytes
);
207 if (tevent_req_nomem(subreq
, req
)) {
208 return tevent_req_post(req
, ev
);
210 tevent_req_set_callback(subreq
, cli_session_setup_lanman2_done
, req
);
214 static void cli_session_setup_lanman2_done(struct tevent_req
*subreq
)
216 struct tevent_req
*req
= tevent_req_callback_data(
217 subreq
, struct tevent_req
);
218 struct cli_session_setup_lanman2_state
*state
= tevent_req_data(
219 req
, struct cli_session_setup_lanman2_state
);
220 struct cli_state
*cli
= state
->cli
;
231 status
= cli_smb_recv(subreq
, state
, &in
, 3, &wct
, &vwv
,
234 if (!NT_STATUS_IS_OK(status
)) {
235 tevent_req_nterror(req
, status
);
239 inhdr
= in
+ NBT_HDR_SIZE
;
242 cli_state_set_uid(state
->cli
, SVAL(inhdr
, HDR_UID
));
244 status
= smb_bytes_talloc_string(cli
,
251 if (!NT_STATUS_IS_OK(status
)) {
252 tevent_req_nterror(req
, status
);
257 status
= smb_bytes_talloc_string(cli
,
264 if (!NT_STATUS_IS_OK(status
)) {
265 tevent_req_nterror(req
, status
);
270 status
= smb_bytes_talloc_string(cli
,
277 if (!NT_STATUS_IS_OK(status
)) {
278 tevent_req_nterror(req
, status
);
283 status
= cli_set_username(cli
, state
->user
);
284 if (tevent_req_nterror(req
, status
)) {
287 tevent_req_done(req
);
290 static NTSTATUS
cli_session_setup_lanman2_recv(struct tevent_req
*req
)
292 return tevent_req_simple_recv_ntstatus(req
);
295 /****************************************************************************
296 Work out suitable capabilities to offer the server.
297 ****************************************************************************/
299 static uint32_t cli_session_setup_capabilities(struct cli_state
*cli
,
300 uint32_t sesssetup_capabilities
)
302 uint32_t client_capabilities
= smb1cli_conn_capabilities(cli
->conn
);
305 * We only send capabilities based on the mask for:
306 * - client only flags
307 * - flags used in both directions
309 * We do not echo the server only flags, except some legacy flags.
311 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
312 * CAP_LARGE_WRITEX in order to allow us to do large reads
313 * against old Samba releases (<= 3.6.x).
315 client_capabilities
&= (SMB_CAP_BOTH_MASK
| SMB_CAP_LEGACY_CLIENT_MASK
);
318 * Session Setup specific flags CAP_DYNAMIC_REAUTH
319 * and CAP_EXTENDED_SECURITY are passed by the caller.
320 * We need that in order to do guest logins even if
321 * CAP_EXTENDED_SECURITY is negotiated.
323 client_capabilities
&= ~(CAP_DYNAMIC_REAUTH
|CAP_EXTENDED_SECURITY
);
324 sesssetup_capabilities
&= (CAP_DYNAMIC_REAUTH
|CAP_EXTENDED_SECURITY
);
325 client_capabilities
|= sesssetup_capabilities
;
327 return client_capabilities
;
330 /****************************************************************************
331 Do a NT1 guest session setup.
332 ****************************************************************************/
334 struct cli_session_setup_guest_state
{
335 struct cli_state
*cli
;
340 static void cli_session_setup_guest_done(struct tevent_req
*subreq
);
342 struct tevent_req
*cli_session_setup_guest_create(TALLOC_CTX
*mem_ctx
,
343 struct tevent_context
*ev
,
344 struct cli_state
*cli
,
345 struct tevent_req
**psmbreq
)
347 struct tevent_req
*req
, *subreq
;
348 struct cli_session_setup_guest_state
*state
;
352 req
= tevent_req_create(mem_ctx
, &state
,
353 struct cli_session_setup_guest_state
);
360 SCVAL(vwv
+0, 0, 0xFF);
363 SSVAL(vwv
+2, 0, CLI_BUFFER_SIZE
);
365 SSVAL(vwv
+4, 0, cli_state_get_vc_num(cli
));
366 SIVAL(vwv
+5, 0, smb1cli_conn_server_session_key(cli
->conn
));
371 SIVAL(vwv
+11, 0, cli_session_setup_capabilities(cli
, 0));
373 bytes
= talloc_array(state
, uint8_t, 0);
375 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "", 1, /* username */
377 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "", 1, /* workgroup */
379 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "Unix", 5, NULL
);
380 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "Samba", 6, NULL
);
387 state
->bytes
.iov_base
= (void *)bytes
;
388 state
->bytes
.iov_len
= talloc_get_size(bytes
);
390 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBsesssetupX
, 0, 13, vwv
,
392 if (subreq
== NULL
) {
396 tevent_req_set_callback(subreq
, cli_session_setup_guest_done
, req
);
401 struct tevent_req
*cli_session_setup_guest_send(TALLOC_CTX
*mem_ctx
,
402 struct tevent_context
*ev
,
403 struct cli_state
*cli
)
405 struct tevent_req
*req
, *subreq
;
408 req
= cli_session_setup_guest_create(mem_ctx
, ev
, cli
, &subreq
);
413 status
= smb1cli_req_chain_submit(&subreq
, 1);
414 if (!NT_STATUS_IS_OK(status
)) {
415 tevent_req_nterror(req
, status
);
416 return tevent_req_post(req
, ev
);
421 static void cli_session_setup_guest_done(struct tevent_req
*subreq
)
423 struct tevent_req
*req
= tevent_req_callback_data(
424 subreq
, struct tevent_req
);
425 struct cli_session_setup_guest_state
*state
= tevent_req_data(
426 req
, struct cli_session_setup_guest_state
);
427 struct cli_state
*cli
= state
->cli
;
438 status
= cli_smb_recv(subreq
, state
, &in
, 3, &wct
, &vwv
,
441 if (!NT_STATUS_IS_OK(status
)) {
442 tevent_req_nterror(req
, status
);
446 inhdr
= in
+ NBT_HDR_SIZE
;
449 cli_state_set_uid(state
->cli
, SVAL(inhdr
, HDR_UID
));
451 status
= smb_bytes_talloc_string(cli
,
458 if (!NT_STATUS_IS_OK(status
)) {
459 tevent_req_nterror(req
, status
);
464 status
= smb_bytes_talloc_string(cli
,
471 if (!NT_STATUS_IS_OK(status
)) {
472 tevent_req_nterror(req
, status
);
477 status
= smb_bytes_talloc_string(cli
,
484 if (!NT_STATUS_IS_OK(status
)) {
485 tevent_req_nterror(req
, status
);
490 status
= cli_set_username(cli
, "");
491 if (!NT_STATUS_IS_OK(status
)) {
492 tevent_req_nterror(req
, status
);
495 tevent_req_done(req
);
498 NTSTATUS
cli_session_setup_guest_recv(struct tevent_req
*req
)
500 return tevent_req_simple_recv_ntstatus(req
);
503 /****************************************************************************
504 Do a NT1 plaintext session setup.
505 ****************************************************************************/
507 struct cli_session_setup_plain_state
{
508 struct cli_state
*cli
;
513 static void cli_session_setup_plain_done(struct tevent_req
*subreq
);
515 static struct tevent_req
*cli_session_setup_plain_send(
516 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
517 struct cli_state
*cli
,
518 const char *user
, const char *pass
, const char *workgroup
)
520 struct tevent_req
*req
, *subreq
;
521 struct cli_session_setup_plain_state
*state
;
527 req
= tevent_req_create(mem_ctx
, &state
,
528 struct cli_session_setup_plain_state
);
536 SCVAL(vwv
+0, 0, 0xff);
539 SSVAL(vwv
+2, 0, CLI_BUFFER_SIZE
);
541 SSVAL(vwv
+4, 0, cli_state_get_vc_num(cli
));
542 SIVAL(vwv
+5, 0, smb1cli_conn_server_session_key(cli
->conn
));
547 SIVAL(vwv
+11, 0, cli_session_setup_capabilities(cli
, 0));
549 bytes
= talloc_array(state
, uint8_t, 0);
550 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), pass
, strlen(pass
)+1,
552 if (tevent_req_nomem(bytes
, req
)) {
553 return tevent_req_post(req
, ev
);
555 SSVAL(vwv
+ (smbXcli_conn_use_unicode(cli
->conn
) ? 8 : 7), 0, passlen
);
557 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
),
558 user
, strlen(user
)+1, NULL
);
559 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
),
560 workgroup
, strlen(workgroup
)+1, NULL
);
561 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
),
564 version
= talloc_asprintf(talloc_tos(), "Samba %s",
565 samba_version_string());
566 if (tevent_req_nomem(version
, req
)){
567 return tevent_req_post(req
, ev
);
569 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
),
570 version
, strlen(version
)+1, NULL
);
571 TALLOC_FREE(version
);
573 if (tevent_req_nomem(bytes
, req
)) {
574 return tevent_req_post(req
, ev
);
577 subreq
= cli_smb_send(state
, ev
, cli
, SMBsesssetupX
, 0, 13, vwv
,
578 talloc_get_size(bytes
), bytes
);
579 if (tevent_req_nomem(subreq
, req
)) {
580 return tevent_req_post(req
, ev
);
582 tevent_req_set_callback(subreq
, cli_session_setup_plain_done
, req
);
586 static void cli_session_setup_plain_done(struct tevent_req
*subreq
)
588 struct tevent_req
*req
= tevent_req_callback_data(
589 subreq
, struct tevent_req
);
590 struct cli_session_setup_plain_state
*state
= tevent_req_data(
591 req
, struct cli_session_setup_plain_state
);
592 struct cli_state
*cli
= state
->cli
;
603 status
= cli_smb_recv(subreq
, state
, &in
, 3, &wct
, &vwv
,
606 if (tevent_req_nterror(req
, status
)) {
610 inhdr
= in
+ NBT_HDR_SIZE
;
613 cli_state_set_uid(state
->cli
, SVAL(inhdr
, HDR_UID
));
615 status
= smb_bytes_talloc_string(cli
,
622 if (!NT_STATUS_IS_OK(status
)) {
623 tevent_req_nterror(req
, status
);
628 status
= smb_bytes_talloc_string(cli
,
635 if (!NT_STATUS_IS_OK(status
)) {
636 tevent_req_nterror(req
, status
);
641 status
= smb_bytes_talloc_string(cli
,
648 if (!NT_STATUS_IS_OK(status
)) {
649 tevent_req_nterror(req
, status
);
654 status
= cli_set_username(cli
, state
->user
);
655 if (tevent_req_nterror(req
, status
)) {
659 tevent_req_done(req
);
662 static NTSTATUS
cli_session_setup_plain_recv(struct tevent_req
*req
)
664 return tevent_req_simple_recv_ntstatus(req
);
667 /****************************************************************************
668 do a NT1 NTLM/LM encrypted session setup - for when extended security
670 @param cli client state to create do session setup on
672 @param pass *either* cleartext password (passlen !=24) or LM response.
673 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
674 @param workgroup The user's domain.
675 ****************************************************************************/
677 struct cli_session_setup_nt1_state
{
678 struct cli_state
*cli
;
681 DATA_BLOB session_key
;
685 static void cli_session_setup_nt1_done(struct tevent_req
*subreq
);
687 static struct tevent_req
*cli_session_setup_nt1_send(
688 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
689 struct cli_state
*cli
, const char *user
,
690 const char *pass
, size_t passlen
,
691 const char *ntpass
, size_t ntpasslen
,
692 const char *workgroup
)
694 struct tevent_req
*req
, *subreq
;
695 struct cli_session_setup_nt1_state
*state
;
696 DATA_BLOB lm_response
= data_blob_null
;
697 DATA_BLOB nt_response
= data_blob_null
;
698 DATA_BLOB session_key
= data_blob_null
;
701 char *workgroup_upper
;
703 req
= tevent_req_create(mem_ctx
, &state
,
704 struct cli_session_setup_nt1_state
);
713 /* do nothing - guest login */
714 } else if (passlen
!= 24) {
715 if (lp_client_ntlmv2_auth()) {
716 DATA_BLOB server_chal
;
717 DATA_BLOB names_blob
;
720 data_blob_const(smb1cli_conn_server_challenge(cli
->conn
),
724 * note that the 'workgroup' here is a best
725 * guess - we don't know the server's domain
726 * at this point. Windows clients also don't
729 names_blob
= NTLMv2_generate_names_blob(
730 NULL
, NULL
, workgroup
);
732 if (tevent_req_nomem(names_blob
.data
, req
)) {
733 return tevent_req_post(req
, ev
);
736 if (!SMBNTLMv2encrypt(NULL
, user
, workgroup
, pass
,
737 &server_chal
, &names_blob
,
738 &lm_response
, &nt_response
,
739 NULL
, &session_key
)) {
740 data_blob_free(&names_blob
);
742 req
, NT_STATUS_ACCESS_DENIED
);
743 return tevent_req_post(req
, ev
);
745 data_blob_free(&names_blob
);
749 E_md4hash(pass
, nt_hash
);
752 nt_response
= data_blob_null
;
754 nt_response
= data_blob(NULL
, 24);
755 if (tevent_req_nomem(nt_response
.data
, req
)) {
756 return tevent_req_post(req
, ev
);
759 SMBNTencrypt(pass
, smb1cli_conn_server_challenge(cli
->conn
),
762 /* non encrypted password supplied. Ignore ntpass. */
763 if (lp_client_lanman_auth()) {
765 lm_response
= data_blob(NULL
, 24);
766 if (tevent_req_nomem(lm_response
.data
, req
)) {
767 return tevent_req_post(req
, ev
);
770 if (!SMBencrypt(pass
,
771 smb1cli_conn_server_challenge(cli
->conn
),
774 * Oops, the LM response is
775 * invalid, just put the NT
776 * response there instead
778 data_blob_free(&lm_response
);
779 lm_response
= data_blob(
785 * LM disabled, place NT# in LM field
788 lm_response
= data_blob(
789 nt_response
.data
, nt_response
.length
);
792 if (tevent_req_nomem(lm_response
.data
, req
)) {
793 return tevent_req_post(req
, ev
);
796 session_key
= data_blob(NULL
, 16);
797 if (tevent_req_nomem(session_key
.data
, req
)) {
798 return tevent_req_post(req
, ev
);
801 E_deshash(pass
, session_key
.data
);
802 memset(&session_key
.data
[8], '\0', 8);
804 SMBsesskeygen_ntv1(nt_hash
, session_key
.data
);
808 /* pre-encrypted password supplied. Only used for
809 security=server, can't do
810 signing because we don't have original key */
812 lm_response
= data_blob(pass
, passlen
);
813 if (tevent_req_nomem(lm_response
.data
, req
)) {
814 return tevent_req_post(req
, ev
);
817 nt_response
= data_blob(ntpass
, ntpasslen
);
818 if (tevent_req_nomem(nt_response
.data
, req
)) {
819 return tevent_req_post(req
, ev
);
824 state
->response
= data_blob_talloc(
825 state
, lm_response
.data
, lm_response
.length
);
827 state
->response
= data_blob_talloc(
828 state
, nt_response
.data
, nt_response
.length
);
830 if (tevent_req_nomem(state
->response
.data
, req
)) {
831 return tevent_req_post(req
, ev
);
834 if (session_key
.data
) {
835 state
->session_key
= data_blob_talloc(
836 state
, session_key
.data
, session_key
.length
);
837 if (tevent_req_nomem(state
->session_key
.data
, req
)) {
838 return tevent_req_post(req
, ev
);
841 data_blob_free(&session_key
);
843 SCVAL(vwv
+0, 0, 0xff);
846 SSVAL(vwv
+2, 0, CLI_BUFFER_SIZE
);
848 SSVAL(vwv
+4, 0, cli_state_get_vc_num(cli
));
849 SIVAL(vwv
+5, 0, smb1cli_conn_server_session_key(cli
->conn
));
850 SSVAL(vwv
+7, 0, lm_response
.length
);
851 SSVAL(vwv
+8, 0, nt_response
.length
);
854 SIVAL(vwv
+11, 0, cli_session_setup_capabilities(cli
, 0));
856 bytes
= talloc_array(state
, uint8_t,
857 lm_response
.length
+ nt_response
.length
);
858 if (tevent_req_nomem(bytes
, req
)) {
859 return tevent_req_post(req
, ev
);
861 if (lm_response
.length
!= 0) {
862 memcpy(bytes
, lm_response
.data
, lm_response
.length
);
864 if (nt_response
.length
!= 0) {
865 memcpy(bytes
+ lm_response
.length
,
866 nt_response
.data
, nt_response
.length
);
868 data_blob_free(&lm_response
);
869 data_blob_free(&nt_response
);
871 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
),
872 user
, strlen(user
)+1, NULL
);
875 * Upper case here might help some NTLMv2 implementations
877 workgroup_upper
= talloc_strdup_upper(talloc_tos(), workgroup
);
878 if (tevent_req_nomem(workgroup_upper
, req
)) {
879 return tevent_req_post(req
, ev
);
881 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
),
882 workgroup_upper
, strlen(workgroup_upper
)+1,
884 TALLOC_FREE(workgroup_upper
);
886 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "Unix", 5, NULL
);
887 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "Samba", 6, NULL
);
888 if (tevent_req_nomem(bytes
, req
)) {
889 return tevent_req_post(req
, ev
);
892 subreq
= cli_smb_send(state
, ev
, cli
, SMBsesssetupX
, 0, 13, vwv
,
893 talloc_get_size(bytes
), bytes
);
894 if (tevent_req_nomem(subreq
, req
)) {
895 return tevent_req_post(req
, ev
);
897 tevent_req_set_callback(subreq
, cli_session_setup_nt1_done
, req
);
901 static void cli_session_setup_nt1_done(struct tevent_req
*subreq
)
903 struct tevent_req
*req
= tevent_req_callback_data(
904 subreq
, struct tevent_req
);
905 struct cli_session_setup_nt1_state
*state
= tevent_req_data(
906 req
, struct cli_session_setup_nt1_state
);
907 struct cli_state
*cli
= state
->cli
;
918 status
= cli_smb_recv(subreq
, state
, &in
, 3, &wct
, &vwv
,
921 if (!NT_STATUS_IS_OK(status
)) {
922 tevent_req_nterror(req
, status
);
926 inhdr
= in
+ NBT_HDR_SIZE
;
929 cli_state_set_uid(state
->cli
, SVAL(inhdr
, HDR_UID
));
931 status
= smb_bytes_talloc_string(cli
,
937 if (!NT_STATUS_IS_OK(status
)) {
938 tevent_req_nterror(req
, status
);
943 status
= smb_bytes_talloc_string(cli
,
949 if (!NT_STATUS_IS_OK(status
)) {
950 tevent_req_nterror(req
, status
);
955 status
= smb_bytes_talloc_string(cli
,
961 if (!NT_STATUS_IS_OK(status
)) {
962 tevent_req_nterror(req
, status
);
967 status
= cli_set_username(cli
, state
->user
);
968 if (tevent_req_nterror(req
, status
)) {
971 if (smb1cli_conn_activate_signing(cli
->conn
, state
->session_key
, state
->response
)
972 && !smb1cli_conn_check_signing(cli
->conn
, (uint8_t *)in
, 1)) {
973 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
976 if (state
->session_key
.data
) {
977 struct smbXcli_session
*session
= state
->cli
->smb1
.session
;
979 status
= smb1cli_session_set_session_key(session
,
981 if (tevent_req_nterror(req
, status
)) {
985 tevent_req_done(req
);
988 static NTSTATUS
cli_session_setup_nt1_recv(struct tevent_req
*req
)
990 return tevent_req_simple_recv_ntstatus(req
);
993 /* The following is calculated from :
995 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
996 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1000 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1002 struct cli_sesssetup_blob_state
{
1003 struct tevent_context
*ev
;
1004 struct cli_state
*cli
;
1006 uint16_t max_blob_size
;
1010 DATA_BLOB smb2_blob
;
1011 struct iovec
*recv_iov
;
1018 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state
*state
,
1019 struct tevent_req
**psubreq
);
1020 static void cli_sesssetup_blob_done(struct tevent_req
*subreq
);
1022 static struct tevent_req
*cli_sesssetup_blob_send(TALLOC_CTX
*mem_ctx
,
1023 struct tevent_context
*ev
,
1024 struct cli_state
*cli
,
1027 struct tevent_req
*req
, *subreq
;
1028 struct cli_sesssetup_blob_state
*state
;
1029 uint32_t usable_space
;
1031 req
= tevent_req_create(mem_ctx
, &state
,
1032 struct cli_sesssetup_blob_state
);
1040 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1041 usable_space
= UINT16_MAX
;
1043 usable_space
= cli_state_available_size(cli
,
1044 BASE_SESSSETUP_BLOB_PACKET_SIZE
);
1047 if (usable_space
== 0) {
1048 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1049 "(not possible to send %u bytes)\n",
1050 BASE_SESSSETUP_BLOB_PACKET_SIZE
+ 1));
1051 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1052 return tevent_req_post(req
, ev
);
1054 state
->max_blob_size
= MIN(usable_space
, 0xFFFF);
1056 if (!cli_sesssetup_blob_next(state
, &subreq
)) {
1057 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
1058 return tevent_req_post(req
, ev
);
1060 tevent_req_set_callback(subreq
, cli_sesssetup_blob_done
, req
);
1064 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state
*state
,
1065 struct tevent_req
**psubreq
)
1067 struct tevent_req
*subreq
;
1070 thistime
= MIN(state
->blob
.length
, state
->max_blob_size
);
1072 if (smbXcli_conn_protocol(state
->cli
->conn
) >= PROTOCOL_SMB2_02
) {
1074 state
->smb2_blob
.data
= state
->blob
.data
;
1075 state
->smb2_blob
.length
= thistime
;
1077 state
->blob
.data
+= thistime
;
1078 state
->blob
.length
-= thistime
;
1080 subreq
= smb2cli_session_setup_send(state
, state
->ev
,
1082 state
->cli
->timeout
,
1083 state
->cli
->smb2
.session
,
1085 SMB2_CAP_DFS
, /* in_capabilities */
1087 0, /* in_previous_session_id */
1089 if (subreq
== NULL
) {
1096 SCVAL(state
->vwv
+0, 0, 0xFF);
1097 SCVAL(state
->vwv
+0, 1, 0);
1098 SSVAL(state
->vwv
+1, 0, 0);
1099 SSVAL(state
->vwv
+2, 0, CLI_BUFFER_SIZE
);
1100 SSVAL(state
->vwv
+3, 0, 2);
1101 SSVAL(state
->vwv
+4, 0, 1);
1102 SIVAL(state
->vwv
+5, 0, 0);
1104 SSVAL(state
->vwv
+7, 0, thistime
);
1106 SSVAL(state
->vwv
+8, 0, 0);
1107 SSVAL(state
->vwv
+9, 0, 0);
1108 SIVAL(state
->vwv
+10, 0,
1109 cli_session_setup_capabilities(state
->cli
, CAP_EXTENDED_SECURITY
));
1111 state
->buf
= (uint8_t *)talloc_memdup(state
, state
->blob
.data
,
1113 if (state
->buf
== NULL
) {
1116 state
->blob
.data
+= thistime
;
1117 state
->blob
.length
-= thistime
;
1119 state
->buf
= smb_bytes_push_str(state
->buf
, smbXcli_conn_use_unicode(state
->cli
->conn
),
1121 state
->buf
= smb_bytes_push_str(state
->buf
, smbXcli_conn_use_unicode(state
->cli
->conn
),
1123 if (state
->buf
== NULL
) {
1126 subreq
= cli_smb_send(state
, state
->ev
, state
->cli
, SMBsesssetupX
, 0,
1128 talloc_get_size(state
->buf
), state
->buf
);
1129 if (subreq
== NULL
) {
1136 static void cli_sesssetup_blob_done(struct tevent_req
*subreq
)
1138 struct tevent_req
*req
= tevent_req_callback_data(
1139 subreq
, struct tevent_req
);
1140 struct cli_sesssetup_blob_state
*state
= tevent_req_data(
1141 req
, struct cli_sesssetup_blob_state
);
1142 struct cli_state
*cli
= state
->cli
;
1149 uint16_t blob_length
;
1154 if (smbXcli_conn_protocol(state
->cli
->conn
) >= PROTOCOL_SMB2_02
) {
1155 status
= smb2cli_session_setup_recv(subreq
, state
,
1159 status
= cli_smb_recv(subreq
, state
, &in
, 4, &wct
, &vwv
,
1160 &num_bytes
, &bytes
);
1161 TALLOC_FREE(state
->buf
);
1163 TALLOC_FREE(subreq
);
1164 if (!NT_STATUS_IS_OK(status
)
1165 && !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1166 tevent_req_nterror(req
, status
);
1170 state
->status
= status
;
1172 if (smbXcli_conn_protocol(state
->cli
->conn
) >= PROTOCOL_SMB2_02
) {
1177 inhdr
= in
+ NBT_HDR_SIZE
;
1178 cli_state_set_uid(state
->cli
, SVAL(inhdr
, HDR_UID
));
1180 blob_length
= SVAL(vwv
+3, 0);
1181 if (blob_length
> num_bytes
) {
1182 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
1185 state
->ret_blob
= data_blob_const(bytes
, blob_length
);
1187 p
= bytes
+ blob_length
;
1189 status
= smb_bytes_talloc_string(cli
,
1196 if (!NT_STATUS_IS_OK(status
)) {
1197 tevent_req_nterror(req
, status
);
1202 status
= smb_bytes_talloc_string(cli
,
1209 if (!NT_STATUS_IS_OK(status
)) {
1210 tevent_req_nterror(req
, status
);
1215 status
= smb_bytes_talloc_string(cli
,
1217 &cli
->server_domain
,
1222 if (!NT_STATUS_IS_OK(status
)) {
1223 tevent_req_nterror(req
, status
);
1229 if (state
->blob
.length
!= 0) {
1233 if (!cli_sesssetup_blob_next(state
, &subreq
)) {
1234 tevent_req_oom(req
);
1237 tevent_req_set_callback(subreq
, cli_sesssetup_blob_done
, req
);
1240 tevent_req_done(req
);
1243 static NTSTATUS
cli_sesssetup_blob_recv(struct tevent_req
*req
,
1244 TALLOC_CTX
*mem_ctx
,
1247 struct iovec
**precv_iov
)
1249 struct cli_sesssetup_blob_state
*state
= tevent_req_data(
1250 req
, struct cli_sesssetup_blob_state
);
1253 struct iovec
*recv_iov
;
1255 if (tevent_req_is_nterror(req
, &status
)) {
1256 TALLOC_FREE(state
->cli
->smb2
.session
);
1257 cli_state_set_uid(state
->cli
, UID_FIELD_INVALID
);
1261 inbuf
= talloc_move(mem_ctx
, &state
->inbuf
);
1262 recv_iov
= talloc_move(mem_ctx
, &state
->recv_iov
);
1263 if (pblob
!= NULL
) {
1264 *pblob
= state
->ret_blob
;
1266 if (pinbuf
!= NULL
) {
1269 if (precv_iov
!= NULL
) {
1270 *precv_iov
= recv_iov
;
1272 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1273 return state
->status
;
1278 /****************************************************************************
1279 Use in-memory credentials cache
1280 ****************************************************************************/
1282 static void use_in_memory_ccache(void) {
1283 setenv(KRB5_ENV_CCNAME
, "MEMORY:cliconnect", 1);
1286 /****************************************************************************
1287 Do a spnego/kerberos encrypted session setup.
1288 ****************************************************************************/
1290 struct cli_session_setup_kerberos_state
{
1291 struct cli_state
*cli
;
1292 DATA_BLOB negTokenTarg
;
1293 DATA_BLOB session_key_krb5
;
1294 ADS_STATUS ads_status
;
1297 static void cli_session_setup_kerberos_done(struct tevent_req
*subreq
);
1299 static struct tevent_req
*cli_session_setup_kerberos_send(
1300 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
, struct cli_state
*cli
,
1301 const char *principal
)
1303 struct tevent_req
*req
, *subreq
;
1304 struct cli_session_setup_kerberos_state
*state
;
1307 DEBUG(2,("Doing kerberos session setup\n"));
1309 req
= tevent_req_create(mem_ctx
, &state
,
1310 struct cli_session_setup_kerberos_state
);
1315 state
->ads_status
= ADS_SUCCESS
;
1318 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1319 * we have to acquire a ticket. To be fixed later :-)
1321 rc
= spnego_gen_krb5_negTokenInit(state
, principal
, 0, &state
->negTokenTarg
,
1322 &state
->session_key_krb5
, 0, NULL
, NULL
);
1324 DEBUG(1, ("cli_session_setup_kerberos: "
1325 "spnego_gen_krb5_negTokenInit failed: %s\n",
1326 error_message(rc
)));
1327 state
->ads_status
= ADS_ERROR_KRB5(rc
);
1328 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
1329 return tevent_req_post(req
, ev
);
1333 file_save("negTokenTarg.dat", state
->negTokenTarg
.data
,
1334 state
->negTokenTarg
.length
);
1337 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1338 state
->cli
->smb2
.session
= smbXcli_session_create(cli
,
1340 if (tevent_req_nomem(state
->cli
->smb2
.session
, req
)) {
1341 return tevent_req_post(req
, ev
);
1345 subreq
= cli_sesssetup_blob_send(state
, ev
, cli
, state
->negTokenTarg
);
1346 if (tevent_req_nomem(subreq
, req
)) {
1347 return tevent_req_post(req
, ev
);
1349 tevent_req_set_callback(subreq
, cli_session_setup_kerberos_done
, req
);
1353 static void cli_session_setup_kerberos_done(struct tevent_req
*subreq
)
1355 struct tevent_req
*req
= tevent_req_callback_data(
1356 subreq
, struct tevent_req
);
1357 struct cli_session_setup_kerberos_state
*state
= tevent_req_data(
1358 req
, struct cli_session_setup_kerberos_state
);
1359 uint8_t *inbuf
= NULL
;
1360 struct iovec
*recv_iov
= NULL
;
1363 status
= cli_sesssetup_blob_recv(subreq
, state
,
1364 NULL
, &inbuf
, &recv_iov
);
1365 TALLOC_FREE(subreq
);
1366 if (!NT_STATUS_IS_OK(status
)) {
1367 tevent_req_nterror(req
, status
);
1371 if (smbXcli_conn_protocol(state
->cli
->conn
) >= PROTOCOL_SMB2_02
) {
1372 struct smbXcli_session
*session
= state
->cli
->smb2
.session
;
1373 status
= smb2cli_session_set_session_key(session
,
1374 state
->session_key_krb5
,
1376 if (tevent_req_nterror(req
, status
)) {
1380 struct smbXcli_session
*session
= state
->cli
->smb1
.session
;
1382 status
= smb1cli_session_set_session_key(session
,
1383 state
->session_key_krb5
);
1384 if (tevent_req_nterror(req
, status
)) {
1388 if (smb1cli_conn_activate_signing(state
->cli
->conn
, state
->session_key_krb5
,
1390 && !smb1cli_conn_check_signing(state
->cli
->conn
, inbuf
, 1)) {
1391 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1396 tevent_req_done(req
);
1399 static ADS_STATUS
cli_session_setup_kerberos_recv(struct tevent_req
*req
)
1401 struct cli_session_setup_kerberos_state
*state
= tevent_req_data(
1402 req
, struct cli_session_setup_kerberos_state
);
1405 if (tevent_req_is_nterror(req
, &status
)) {
1406 return ADS_ERROR_NT(status
);
1408 return state
->ads_status
;
1411 #endif /* HAVE_KRB5 */
1413 /****************************************************************************
1414 Do a spnego/NTLMSSP encrypted session setup.
1415 ****************************************************************************/
1417 struct cli_session_setup_ntlmssp_state
{
1418 struct tevent_context
*ev
;
1419 struct cli_state
*cli
;
1420 struct ntlmssp_state
*ntlmssp_state
;
1425 static int cli_session_setup_ntlmssp_state_destructor(
1426 struct cli_session_setup_ntlmssp_state
*state
)
1428 if (state
->ntlmssp_state
!= NULL
) {
1429 TALLOC_FREE(state
->ntlmssp_state
);
1434 static void cli_session_setup_ntlmssp_done(struct tevent_req
*req
);
1436 static struct tevent_req
*cli_session_setup_ntlmssp_send(
1437 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
, struct cli_state
*cli
,
1438 const char *user
, const char *pass
, const char *domain
)
1440 struct tevent_req
*req
, *subreq
;
1441 struct cli_session_setup_ntlmssp_state
*state
;
1444 const char *OIDs_ntlm
[] = {OID_NTLMSSP
, NULL
};
1446 req
= tevent_req_create(mem_ctx
, &state
,
1447 struct cli_session_setup_ntlmssp_state
);
1455 state
->ntlmssp_state
= NULL
;
1456 talloc_set_destructor(
1457 state
, cli_session_setup_ntlmssp_state_destructor
);
1459 status
= ntlmssp_client_start(state
,
1462 lp_client_ntlmv2_auth(),
1463 &state
->ntlmssp_state
);
1464 if (!NT_STATUS_IS_OK(status
)) {
1467 ntlmssp_want_feature(state
->ntlmssp_state
,
1468 NTLMSSP_FEATURE_SESSION_KEY
);
1469 if (cli
->use_ccache
) {
1470 ntlmssp_want_feature(state
->ntlmssp_state
,
1471 NTLMSSP_FEATURE_CCACHE
);
1473 status
= ntlmssp_set_username(state
->ntlmssp_state
, user
);
1474 if (!NT_STATUS_IS_OK(status
)) {
1477 status
= ntlmssp_set_domain(state
->ntlmssp_state
, domain
);
1478 if (!NT_STATUS_IS_OK(status
)) {
1481 if (cli
->pw_nt_hash
) {
1482 status
= ntlmssp_set_password_hash(state
->ntlmssp_state
, pass
);
1484 status
= ntlmssp_set_password(state
->ntlmssp_state
, pass
);
1486 if (!NT_STATUS_IS_OK(status
)) {
1489 status
= ntlmssp_update(state
->ntlmssp_state
, data_blob_null
,
1491 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1495 state
->blob_out
= spnego_gen_negTokenInit(state
, OIDs_ntlm
, &blob_out
, NULL
);
1496 data_blob_free(&blob_out
);
1498 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1499 state
->cli
->smb2
.session
= smbXcli_session_create(cli
,
1501 if (tevent_req_nomem(state
->cli
->smb2
.session
, req
)) {
1502 return tevent_req_post(req
, ev
);
1506 subreq
= cli_sesssetup_blob_send(state
, ev
, cli
, state
->blob_out
);
1507 if (tevent_req_nomem(subreq
, req
)) {
1508 return tevent_req_post(req
, ev
);
1510 tevent_req_set_callback(subreq
, cli_session_setup_ntlmssp_done
, req
);
1513 tevent_req_nterror(req
, status
);
1514 return tevent_req_post(req
, ev
);
1517 static void cli_session_setup_ntlmssp_done(struct tevent_req
*subreq
)
1519 struct tevent_req
*req
= tevent_req_callback_data(
1520 subreq
, struct tevent_req
);
1521 struct cli_session_setup_ntlmssp_state
*state
= tevent_req_data(
1522 req
, struct cli_session_setup_ntlmssp_state
);
1523 DATA_BLOB blob_in
, msg_in
, blob_out
;
1524 uint8_t *inbuf
= NULL
;
1525 struct iovec
*recv_iov
= NULL
;
1529 status
= cli_sesssetup_blob_recv(subreq
, talloc_tos(), &blob_in
,
1531 TALLOC_FREE(subreq
);
1532 data_blob_free(&state
->blob_out
);
1534 if (NT_STATUS_IS_OK(status
)) {
1535 if (state
->cli
->server_domain
[0] == '\0') {
1536 TALLOC_FREE(state
->cli
->server_domain
);
1537 state
->cli
->server_domain
= talloc_strdup(state
->cli
,
1538 state
->ntlmssp_state
->server
.netbios_domain
);
1539 if (state
->cli
->server_domain
== NULL
) {
1540 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
1545 if (smbXcli_conn_protocol(state
->cli
->conn
) >= PROTOCOL_SMB2_02
) {
1546 struct smbXcli_session
*session
= state
->cli
->smb2
.session
;
1548 if (ntlmssp_is_anonymous(state
->ntlmssp_state
)) {
1550 * Windows server does not set the
1551 * SMB2_SESSION_FLAG_IS_GUEST nor
1552 * SMB2_SESSION_FLAG_IS_NULL flag.
1554 * This fix makes sure we do not try
1555 * to verify a signature on the final
1556 * session setup response.
1558 TALLOC_FREE(state
->ntlmssp_state
);
1559 tevent_req_done(req
);
1563 status
= smb2cli_session_set_session_key(session
,
1564 state
->ntlmssp_state
->session_key
,
1566 if (tevent_req_nterror(req
, status
)) {
1570 struct smbXcli_session
*session
= state
->cli
->smb1
.session
;
1572 status
= smb1cli_session_set_session_key(session
,
1573 state
->ntlmssp_state
->session_key
);
1574 if (tevent_req_nterror(req
, status
)) {
1578 if (smb1cli_conn_activate_signing(
1579 state
->cli
->conn
, state
->ntlmssp_state
->session_key
,
1581 && !smb1cli_conn_check_signing(state
->cli
->conn
, inbuf
, 1)) {
1582 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1586 TALLOC_FREE(state
->ntlmssp_state
);
1587 tevent_req_done(req
);
1590 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1591 tevent_req_nterror(req
, status
);
1595 if (blob_in
.length
== 0) {
1596 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
1600 if ((state
->turn
== 1)
1601 && NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1602 DATA_BLOB tmp_blob
= data_blob_null
;
1603 /* the server might give us back two challenges */
1604 parse_ret
= spnego_parse_challenge(state
, blob_in
, &msg_in
,
1606 data_blob_free(&tmp_blob
);
1608 parse_ret
= spnego_parse_auth_response(state
, blob_in
, status
,
1609 OID_NTLMSSP
, &msg_in
);
1614 DEBUG(3,("Failed to parse auth response\n"));
1615 if (NT_STATUS_IS_OK(status
)
1616 || NT_STATUS_EQUAL(status
,
1617 NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1619 req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
1624 status
= ntlmssp_update(state
->ntlmssp_state
, msg_in
, &blob_out
);
1626 if (!NT_STATUS_IS_OK(status
)
1627 && !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1628 TALLOC_FREE(state
->ntlmssp_state
);
1629 tevent_req_nterror(req
, status
);
1633 state
->blob_out
= spnego_gen_auth(state
, blob_out
);
1634 if (tevent_req_nomem(state
->blob_out
.data
, req
)) {
1638 subreq
= cli_sesssetup_blob_send(state
, state
->ev
, state
->cli
,
1640 if (tevent_req_nomem(subreq
, req
)) {
1643 tevent_req_set_callback(subreq
, cli_session_setup_ntlmssp_done
, req
);
1646 static NTSTATUS
cli_session_setup_ntlmssp_recv(struct tevent_req
*req
)
1648 struct cli_session_setup_ntlmssp_state
*state
= tevent_req_data(
1649 req
, struct cli_session_setup_ntlmssp_state
);
1652 if (tevent_req_is_nterror(req
, &status
)) {
1653 cli_state_set_uid(state
->cli
, UID_FIELD_INVALID
);
1656 return NT_STATUS_OK
;
1661 static char *cli_session_setup_get_principal(
1662 TALLOC_CTX
*mem_ctx
, const char *spnego_principal
,
1663 const char *remote_name
, const char *dest_realm
)
1665 char *principal
= NULL
;
1667 if (!lp_client_use_spnego_principal() ||
1668 strequal(principal
, ADS_IGNORE_PRINCIPAL
)) {
1669 spnego_principal
= NULL
;
1671 if (spnego_principal
!= NULL
) {
1672 DEBUG(3, ("cli_session_setup_spnego: using spnego provided "
1673 "principal %s\n", spnego_principal
));
1674 return talloc_strdup(mem_ctx
, spnego_principal
);
1676 if (is_ipaddress(remote_name
) ||
1677 strequal(remote_name
, STAR_SMBSERVER
)) {
1681 DEBUG(3, ("cli_session_setup_spnego: using target "
1682 "hostname not SPNEGO principal\n"));
1685 char *realm
= strupper_talloc(talloc_tos(), dest_realm
);
1686 if (realm
== NULL
) {
1689 principal
= talloc_asprintf(talloc_tos(), "cifs/%s@%s",
1690 remote_name
, realm
);
1693 principal
= kerberos_get_principal_from_service_hostname(
1694 talloc_tos(), "cifs", remote_name
, lp_realm());
1696 DEBUG(3, ("cli_session_setup_spnego: guessed server principal=%s\n",
1697 principal
? principal
: "<null>"));
1703 static char *cli_session_setup_get_account(TALLOC_CTX
*mem_ctx
,
1704 const char *principal
)
1708 account
= talloc_strdup(mem_ctx
, principal
);
1709 if (account
== NULL
) {
1712 p
= strchr_m(account
, '@');
1719 /****************************************************************************
1720 Do a spnego encrypted session setup.
1722 user_domain: The shortname of the domain the user/machine is a member of.
1723 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1724 ****************************************************************************/
1726 struct cli_session_setup_spnego_state
{
1727 struct tevent_context
*ev
;
1728 struct cli_state
*cli
;
1730 const char *account
;
1732 const char *user_domain
;
1733 const char *dest_realm
;
1738 static void cli_session_setup_spnego_done_krb(struct tevent_req
*subreq
);
1741 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req
*subreq
);
1743 static struct tevent_req
*cli_session_setup_spnego_send(
1744 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
, struct cli_state
*cli
,
1745 const char *user
, const char *pass
, const char *user_domain
,
1746 const char *dest_realm
)
1748 struct tevent_req
*req
, *subreq
;
1749 struct cli_session_setup_spnego_state
*state
;
1750 char *principal
= NULL
;
1751 char *OIDs
[ASN1_MAX_OIDS
];
1753 const DATA_BLOB
*server_blob
;
1756 req
= tevent_req_create(mem_ctx
, &state
,
1757 struct cli_session_setup_spnego_state
);
1765 state
->user_domain
= user_domain
;
1766 state
->dest_realm
= dest_realm
;
1768 state
->account
= cli_session_setup_get_account(state
, user
);
1769 if (tevent_req_nomem(state
->account
, req
)) {
1770 return tevent_req_post(req
, ev
);
1773 server_blob
= smbXcli_conn_server_gss_blob(cli
->conn
);
1775 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
1776 (unsigned long)server_blob
->length
));
1778 /* the server might not even do spnego */
1779 if (server_blob
->length
== 0) {
1780 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1785 file_save("negprot.dat", cli
->secblob
.data
, cli
->secblob
.length
);
1788 /* The server sent us the first part of the SPNEGO exchange in the
1789 * negprot reply. It is WRONG to depend on the principal sent in the
1790 * negprot reply, but right now we do it. If we don't receive one,
1791 * we try to best guess, then fall back to NTLM. */
1792 if (!spnego_parse_negTokenInit(state
, *server_blob
, OIDs
,
1793 &principal
, NULL
) ||
1795 state
->result
= ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
1796 tevent_req_done(req
);
1797 return tevent_req_post(req
, ev
);
1800 /* make sure the server understands kerberos */
1801 for (i
=0;OIDs
[i
];i
++) {
1803 DEBUG(3,("got OID=%s\n", OIDs
[i
]));
1805 DEBUGADD(3,("got OID=%s\n", OIDs
[i
]));
1806 if (strcmp(OIDs
[i
], OID_KERBEROS5_OLD
) == 0 ||
1807 strcmp(OIDs
[i
], OID_KERBEROS5
) == 0) {
1808 cli
->got_kerberos_mechanism
= True
;
1810 talloc_free(OIDs
[i
]);
1813 DEBUG(3,("got principal=%s\n", principal
? principal
: "<null>"));
1815 status
= cli_set_username(cli
, user
);
1816 if (!NT_STATUS_IS_OK(status
)) {
1817 state
->result
= ADS_ERROR_NT(status
);
1818 tevent_req_done(req
);
1819 return tevent_req_post(req
, ev
);
1823 /* If password is set we reauthenticate to kerberos server
1824 * and do not store results */
1826 if (user
&& *user
&& cli
->got_kerberos_mechanism
&& cli
->use_kerberos
) {
1827 const char *remote_name
= smbXcli_conn_remote_name(cli
->conn
);
1830 if (pass
&& *pass
) {
1833 use_in_memory_ccache();
1834 ret
= kerberos_kinit_password(user
, pass
, 0 /* no time correction for now */, NULL
);
1837 TALLOC_FREE(principal
);
1838 DEBUG(0, ("Kinit failed: %s\n", error_message(ret
)));
1839 if (cli
->fallback_after_kerberos
)
1841 state
->result
= ADS_ERROR_KRB5(ret
);
1842 tevent_req_done(req
);
1843 return tevent_req_post(req
, ev
);
1847 tmp
= cli_session_setup_get_principal(
1848 talloc_tos(), principal
, remote_name
, dest_realm
);
1849 TALLOC_FREE(principal
);
1853 subreq
= cli_session_setup_kerberos_send(
1854 state
, ev
, cli
, principal
);
1855 if (tevent_req_nomem(subreq
, req
)) {
1856 return tevent_req_post(req
, ev
);
1858 tevent_req_set_callback(
1859 subreq
, cli_session_setup_spnego_done_krb
,
1867 subreq
= cli_session_setup_ntlmssp_send(
1868 state
, ev
, cli
, state
->account
, pass
, user_domain
);
1869 if (tevent_req_nomem(subreq
, req
)) {
1870 return tevent_req_post(req
, ev
);
1872 tevent_req_set_callback(
1873 subreq
, cli_session_setup_spnego_done_ntlmssp
, req
);
1878 static void cli_session_setup_spnego_done_krb(struct tevent_req
*subreq
)
1880 struct tevent_req
*req
= tevent_req_callback_data(
1881 subreq
, struct tevent_req
);
1882 struct cli_session_setup_spnego_state
*state
= tevent_req_data(
1883 req
, struct cli_session_setup_spnego_state
);
1885 state
->result
= cli_session_setup_kerberos_recv(subreq
);
1886 TALLOC_FREE(subreq
);
1888 if (ADS_ERR_OK(state
->result
) ||
1889 !state
->cli
->fallback_after_kerberos
) {
1890 tevent_req_done(req
);
1894 subreq
= cli_session_setup_ntlmssp_send(
1895 state
, state
->ev
, state
->cli
, state
->account
, state
->pass
,
1896 state
->user_domain
);
1897 if (tevent_req_nomem(subreq
, req
)) {
1900 tevent_req_set_callback(subreq
, cli_session_setup_spnego_done_ntlmssp
,
1905 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req
*subreq
)
1907 struct tevent_req
*req
= tevent_req_callback_data(
1908 subreq
, struct tevent_req
);
1909 struct cli_session_setup_spnego_state
*state
= tevent_req_data(
1910 req
, struct cli_session_setup_spnego_state
);
1913 status
= cli_session_setup_ntlmssp_recv(subreq
);
1914 TALLOC_FREE(subreq
);
1915 state
->result
= ADS_ERROR_NT(status
);
1916 tevent_req_done(req
);
1919 static ADS_STATUS
cli_session_setup_spnego_recv(struct tevent_req
*req
)
1921 struct cli_session_setup_spnego_state
*state
= tevent_req_data(
1922 req
, struct cli_session_setup_spnego_state
);
1924 return state
->result
;
1927 struct cli_session_setup_state
{
1931 static void cli_session_setup_done_lanman2(struct tevent_req
*subreq
);
1932 static void cli_session_setup_done_spnego(struct tevent_req
*subreq
);
1933 static void cli_session_setup_done_guest(struct tevent_req
*subreq
);
1934 static void cli_session_setup_done_plain(struct tevent_req
*subreq
);
1935 static void cli_session_setup_done_nt1(struct tevent_req
*subreq
);
1937 /****************************************************************************
1938 Send a session setup. The username and workgroup is in UNIX character
1939 format and must be converted to DOS codepage format before sending. If the
1940 password is in plaintext, the same should be done.
1941 ****************************************************************************/
1943 struct tevent_req
*cli_session_setup_send(TALLOC_CTX
*mem_ctx
,
1944 struct tevent_context
*ev
,
1945 struct cli_state
*cli
,
1947 const char *pass
, int passlen
,
1948 const char *ntpass
, int ntpasslen
,
1949 const char *workgroup
)
1951 struct tevent_req
*req
, *subreq
;
1952 struct cli_session_setup_state
*state
;
1955 uint16_t sec_mode
= smb1cli_conn_server_security_mode(cli
->conn
);
1957 req
= tevent_req_create(mem_ctx
, &state
,
1958 struct cli_session_setup_state
);
1964 user2
= talloc_strdup(state
, user
);
1966 user2
= talloc_strdup(state
, "");
1968 if (user2
== NULL
) {
1969 tevent_req_oom(req
);
1970 return tevent_req_post(req
, ev
);
1977 /* allow for workgroups as part of the username */
1978 if ((p
=strchr_m(user2
,'\\')) || (p
=strchr_m(user2
,'/')) ||
1979 (p
=strchr_m(user2
,*lp_winbind_separator()))) {
1982 if (!strupper_m(user2
)) {
1983 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1984 return tevent_req_post(req
, ev
);
1989 if (smbXcli_conn_protocol(cli
->conn
) < PROTOCOL_LANMAN1
) {
1990 tevent_req_done(req
);
1991 return tevent_req_post(req
, ev
);
1994 /* now work out what sort of session setup we are going to
1995 do. I have split this into separate functions to make the
1996 flow a bit easier to understand (tridge) */
1998 /* if its an older server then we have to use the older request format */
2000 if (smbXcli_conn_protocol(cli
->conn
) < PROTOCOL_NT1
) {
2001 if (!lp_client_lanman_auth() && passlen
!= 24 && (*pass
)) {
2002 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2003 " or 'client ntlmv2 auth = yes'\n"));
2004 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2005 return tevent_req_post(req
, ev
);
2008 if ((sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) == 0 &&
2009 !lp_client_plaintext_auth() && (*pass
)) {
2010 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2011 " or 'client ntlmv2 auth = yes'\n"));
2012 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2013 return tevent_req_post(req
, ev
);
2016 subreq
= cli_session_setup_lanman2_send(
2017 state
, ev
, cli
, user
, pass
, passlen
, workgroup
);
2018 if (tevent_req_nomem(subreq
, req
)) {
2019 return tevent_req_post(req
, ev
);
2021 tevent_req_set_callback(subreq
, cli_session_setup_done_lanman2
,
2026 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2027 const char *remote_realm
= cli_state_remote_realm(cli
);
2029 subreq
= cli_session_setup_spnego_send(
2030 state
, ev
, cli
, user
, pass
, workgroup
, remote_realm
);
2031 if (tevent_req_nomem(subreq
, req
)) {
2032 return tevent_req_post(req
, ev
);
2034 tevent_req_set_callback(subreq
, cli_session_setup_done_spnego
,
2039 /* if no user is supplied then we have to do an anonymous connection.
2040 passwords are ignored */
2042 if (!user
|| !*user
) {
2043 subreq
= cli_session_setup_guest_send(state
, ev
, cli
);
2044 if (tevent_req_nomem(subreq
, req
)) {
2045 return tevent_req_post(req
, ev
);
2047 tevent_req_set_callback(subreq
, cli_session_setup_done_guest
,
2052 /* if the server is share level then send a plaintext null
2053 password at this point. The password is sent in the tree
2056 if ((sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
) == 0) {
2057 subreq
= cli_session_setup_plain_send(
2058 state
, ev
, cli
, user
, "", workgroup
);
2059 if (tevent_req_nomem(subreq
, req
)) {
2060 return tevent_req_post(req
, ev
);
2062 tevent_req_set_callback(subreq
, cli_session_setup_done_plain
,
2067 /* if the server doesn't support encryption then we have to use
2068 plaintext. The second password is ignored */
2070 if ((sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) == 0) {
2071 if (!lp_client_plaintext_auth() && (*pass
)) {
2072 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2073 " or 'client ntlmv2 auth = yes'\n"));
2074 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2075 return tevent_req_post(req
, ev
);
2077 subreq
= cli_session_setup_plain_send(
2078 state
, ev
, cli
, user
, pass
, workgroup
);
2079 if (tevent_req_nomem(subreq
, req
)) {
2080 return tevent_req_post(req
, ev
);
2082 tevent_req_set_callback(subreq
, cli_session_setup_done_plain
,
2087 /* if the server supports extended security then use SPNEGO */
2089 if (smb1cli_conn_capabilities(cli
->conn
) & CAP_EXTENDED_SECURITY
) {
2090 const char *remote_realm
= cli_state_remote_realm(cli
);
2092 subreq
= cli_session_setup_spnego_send(
2093 state
, ev
, cli
, user
, pass
, workgroup
, remote_realm
);
2094 if (tevent_req_nomem(subreq
, req
)) {
2095 return tevent_req_post(req
, ev
);
2097 tevent_req_set_callback(subreq
, cli_session_setup_done_spnego
,
2101 /* otherwise do a NT1 style session setup */
2103 subreq
= cli_session_setup_nt1_send(
2104 state
, ev
, cli
, user
, pass
, passlen
, ntpass
, ntpasslen
,
2106 if (tevent_req_nomem(subreq
, req
)) {
2107 return tevent_req_post(req
, ev
);
2109 tevent_req_set_callback(subreq
, cli_session_setup_done_nt1
,
2114 tevent_req_done(req
);
2115 return tevent_req_post(req
, ev
);
2118 static void cli_session_setup_done_lanman2(struct tevent_req
*subreq
)
2120 struct tevent_req
*req
= tevent_req_callback_data(
2121 subreq
, struct tevent_req
);
2124 status
= cli_session_setup_lanman2_recv(subreq
);
2125 TALLOC_FREE(subreq
);
2126 if (!NT_STATUS_IS_OK(status
)) {
2127 tevent_req_nterror(req
, status
);
2130 tevent_req_done(req
);
2133 static void cli_session_setup_done_spnego(struct tevent_req
*subreq
)
2135 struct tevent_req
*req
= tevent_req_callback_data(
2136 subreq
, struct tevent_req
);
2139 status
= cli_session_setup_spnego_recv(subreq
);
2140 TALLOC_FREE(subreq
);
2141 if (!ADS_ERR_OK(status
)) {
2142 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status
)));
2143 tevent_req_nterror(req
, ads_ntstatus(status
));
2146 tevent_req_done(req
);
2149 static void cli_session_setup_done_guest(struct tevent_req
*subreq
)
2151 struct tevent_req
*req
= tevent_req_callback_data(
2152 subreq
, struct tevent_req
);
2155 status
= cli_session_setup_guest_recv(subreq
);
2156 TALLOC_FREE(subreq
);
2157 if (!NT_STATUS_IS_OK(status
)) {
2158 tevent_req_nterror(req
, status
);
2161 tevent_req_done(req
);
2164 static void cli_session_setup_done_plain(struct tevent_req
*subreq
)
2166 struct tevent_req
*req
= tevent_req_callback_data(
2167 subreq
, struct tevent_req
);
2170 status
= cli_session_setup_plain_recv(subreq
);
2171 TALLOC_FREE(subreq
);
2172 if (!NT_STATUS_IS_OK(status
)) {
2173 tevent_req_nterror(req
, status
);
2176 tevent_req_done(req
);
2179 static void cli_session_setup_done_nt1(struct tevent_req
*subreq
)
2181 struct tevent_req
*req
= tevent_req_callback_data(
2182 subreq
, struct tevent_req
);
2185 status
= cli_session_setup_nt1_recv(subreq
);
2186 TALLOC_FREE(subreq
);
2187 if (!NT_STATUS_IS_OK(status
)) {
2188 DEBUG(3, ("cli_session_setup: NT1 session setup "
2189 "failed: %s\n", nt_errstr(status
)));
2190 tevent_req_nterror(req
, status
);
2193 tevent_req_done(req
);
2196 NTSTATUS
cli_session_setup_recv(struct tevent_req
*req
)
2198 return tevent_req_simple_recv_ntstatus(req
);
2201 NTSTATUS
cli_session_setup(struct cli_state
*cli
,
2203 const char *pass
, int passlen
,
2204 const char *ntpass
, int ntpasslen
,
2205 const char *workgroup
)
2207 struct tevent_context
*ev
;
2208 struct tevent_req
*req
;
2209 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2211 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2212 return NT_STATUS_INVALID_PARAMETER
;
2214 ev
= samba_tevent_context_init(talloc_tos());
2218 req
= cli_session_setup_send(ev
, ev
, cli
, user
, pass
, passlen
,
2219 ntpass
, ntpasslen
, workgroup
);
2223 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2226 status
= cli_session_setup_recv(req
);
2232 /****************************************************************************
2234 *****************************************************************************/
2236 struct cli_ulogoff_state
{
2237 struct cli_state
*cli
;
2241 static void cli_ulogoff_done(struct tevent_req
*subreq
);
2243 struct tevent_req
*cli_ulogoff_send(TALLOC_CTX
*mem_ctx
,
2244 struct tevent_context
*ev
,
2245 struct cli_state
*cli
)
2247 struct tevent_req
*req
, *subreq
;
2248 struct cli_ulogoff_state
*state
;
2250 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ulogoff_state
);
2256 SCVAL(state
->vwv
+0, 0, 0xFF);
2257 SCVAL(state
->vwv
+1, 0, 0);
2258 SSVAL(state
->vwv
+2, 0, 0);
2260 subreq
= cli_smb_send(state
, ev
, cli
, SMBulogoffX
, 0, 2, state
->vwv
,
2262 if (tevent_req_nomem(subreq
, req
)) {
2263 return tevent_req_post(req
, ev
);
2265 tevent_req_set_callback(subreq
, cli_ulogoff_done
, req
);
2269 static void cli_ulogoff_done(struct tevent_req
*subreq
)
2271 struct tevent_req
*req
= tevent_req_callback_data(
2272 subreq
, struct tevent_req
);
2273 struct cli_ulogoff_state
*state
= tevent_req_data(
2274 req
, struct cli_ulogoff_state
);
2277 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2278 if (!NT_STATUS_IS_OK(status
)) {
2279 tevent_req_nterror(req
, status
);
2282 cli_state_set_uid(state
->cli
, UID_FIELD_INVALID
);
2283 tevent_req_done(req
);
2286 NTSTATUS
cli_ulogoff_recv(struct tevent_req
*req
)
2288 return tevent_req_simple_recv_ntstatus(req
);
2291 NTSTATUS
cli_ulogoff(struct cli_state
*cli
)
2293 struct tevent_context
*ev
;
2294 struct tevent_req
*req
;
2295 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2297 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2298 return NT_STATUS_INVALID_PARAMETER
;
2300 ev
= samba_tevent_context_init(talloc_tos());
2304 req
= cli_ulogoff_send(ev
, ev
, cli
);
2308 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2311 status
= cli_ulogoff_recv(req
);
2317 /****************************************************************************
2319 ****************************************************************************/
2321 struct cli_tcon_andx_state
{
2322 struct cli_state
*cli
;
2327 static void cli_tcon_andx_done(struct tevent_req
*subreq
);
2329 struct tevent_req
*cli_tcon_andx_create(TALLOC_CTX
*mem_ctx
,
2330 struct tevent_context
*ev
,
2331 struct cli_state
*cli
,
2332 const char *share
, const char *dev
,
2333 const char *pass
, int passlen
,
2334 struct tevent_req
**psmbreq
)
2336 struct tevent_req
*req
, *subreq
;
2337 struct cli_tcon_andx_state
*state
;
2342 uint16_t sec_mode
= smb1cli_conn_server_security_mode(cli
->conn
);
2343 uint16_t tcon_flags
= 0;
2347 req
= tevent_req_create(mem_ctx
, &state
, struct cli_tcon_andx_state
);
2354 cli
->share
= talloc_strdup(cli
, share
);
2359 /* in user level security don't send a password now */
2360 if (sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
) {
2363 } else if (pass
== NULL
) {
2364 DEBUG(1, ("Server not using user level security and no "
2365 "password supplied.\n"));
2369 if ((sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) &&
2370 *pass
&& passlen
!= 24) {
2371 if (!lp_client_lanman_auth()) {
2372 DEBUG(1, ("Server requested LANMAN password "
2373 "(share-level security) but "
2374 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2379 * Non-encrypted passwords - convert to DOS codepage before
2382 SMBencrypt(pass
, smb1cli_conn_server_challenge(cli
->conn
), p24
);
2384 pass
= (const char *)p24
;
2386 if((sec_mode
& (NEGOTIATE_SECURITY_USER_LEVEL
2387 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
))
2391 if (!lp_client_plaintext_auth() && (*pass
)) {
2392 DEBUG(1, ("Server requested PLAINTEXT "
2394 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2399 * Non-encrypted passwords - convert to DOS codepage
2402 tmp_pass
= talloc_array(talloc_tos(), uint8
, 0);
2403 if (tevent_req_nomem(tmp_pass
, req
)) {
2404 return tevent_req_post(req
, ev
);
2406 tmp_pass
= trans2_bytes_push_str(tmp_pass
,
2407 false, /* always DOS */
2411 if (tevent_req_nomem(tmp_pass
, req
)) {
2412 return tevent_req_post(req
, ev
);
2414 pass
= (const char *)tmp_pass
;
2415 passlen
= talloc_get_size(tmp_pass
);
2419 tcon_flags
|= TCONX_FLAG_EXTENDED_RESPONSE
;
2420 tcon_flags
|= TCONX_FLAG_EXTENDED_SIGNATURES
;
2422 SCVAL(vwv
+0, 0, 0xFF);
2425 SSVAL(vwv
+2, 0, tcon_flags
);
2426 SSVAL(vwv
+3, 0, passlen
);
2428 if (passlen
&& pass
) {
2429 bytes
= (uint8_t *)talloc_memdup(state
, pass
, passlen
);
2431 bytes
= talloc_array(state
, uint8_t, 0);
2437 tmp
= talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2438 smbXcli_conn_remote_name(cli
->conn
), share
);
2443 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), tmp
, strlen(tmp
)+1,
2448 * Add the devicetype
2450 tmp
= talloc_strdup_upper(talloc_tos(), dev
);
2455 bytes
= smb_bytes_push_str(bytes
, false, tmp
, strlen(tmp
)+1, NULL
);
2458 if (bytes
== NULL
) {
2463 state
->bytes
.iov_base
= (void *)bytes
;
2464 state
->bytes
.iov_len
= talloc_get_size(bytes
);
2466 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBtconX
, 0, 4, vwv
,
2468 if (subreq
== NULL
) {
2472 tevent_req_set_callback(subreq
, cli_tcon_andx_done
, req
);
2477 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2478 return tevent_req_post(req
, ev
);
2481 struct tevent_req
*cli_tcon_andx_send(TALLOC_CTX
*mem_ctx
,
2482 struct tevent_context
*ev
,
2483 struct cli_state
*cli
,
2484 const char *share
, const char *dev
,
2485 const char *pass
, int passlen
)
2487 struct tevent_req
*req
, *subreq
;
2490 req
= cli_tcon_andx_create(mem_ctx
, ev
, cli
, share
, dev
, pass
, passlen
,
2495 if (subreq
== NULL
) {
2498 status
= smb1cli_req_chain_submit(&subreq
, 1);
2499 if (!NT_STATUS_IS_OK(status
)) {
2500 tevent_req_nterror(req
, status
);
2501 return tevent_req_post(req
, ev
);
2506 static void cli_tcon_andx_done(struct tevent_req
*subreq
)
2508 struct tevent_req
*req
= tevent_req_callback_data(
2509 subreq
, struct tevent_req
);
2510 struct cli_tcon_andx_state
*state
= tevent_req_data(
2511 req
, struct cli_tcon_andx_state
);
2512 struct cli_state
*cli
= state
->cli
;
2520 uint16_t optional_support
= 0;
2522 status
= cli_smb_recv(subreq
, state
, &in
, 0, &wct
, &vwv
,
2523 &num_bytes
, &bytes
);
2524 TALLOC_FREE(subreq
);
2525 if (!NT_STATUS_IS_OK(status
)) {
2526 tevent_req_nterror(req
, status
);
2530 inhdr
= in
+ NBT_HDR_SIZE
;
2533 if (clistr_pull_talloc(cli
,
2534 (const char *)inhdr
,
2535 SVAL(inhdr
, HDR_FLG2
),
2539 STR_TERMINATE
|STR_ASCII
) == -1) {
2540 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
2544 cli
->dev
= talloc_strdup(cli
, "");
2545 if (cli
->dev
== NULL
) {
2546 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
2551 if ((smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_NT1
) && (num_bytes
== 3)) {
2552 /* almost certainly win95 - enable bug fixes */
2557 * Make sure that we have the optional support 16-bit field. WCT > 2.
2558 * Avoids issues when connecting to Win9x boxes sharing files
2561 cli
->dfsroot
= false;
2563 if ((wct
> 2) && (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_LANMAN2
)) {
2564 optional_support
= SVAL(vwv
+2, 0);
2567 if (optional_support
& SMB_SHARE_IN_DFS
) {
2568 cli
->dfsroot
= true;
2571 if (optional_support
& SMB_EXTENDED_SIGNATURES
) {
2572 smb1cli_session_protect_session_key(cli
->smb1
.session
);
2575 cli_state_set_tid(cli
, SVAL(inhdr
, HDR_TID
));
2576 tevent_req_done(req
);
2579 NTSTATUS
cli_tcon_andx_recv(struct tevent_req
*req
)
2581 return tevent_req_simple_recv_ntstatus(req
);
2584 NTSTATUS
cli_tcon_andx(struct cli_state
*cli
, const char *share
,
2585 const char *dev
, const char *pass
, int passlen
)
2587 TALLOC_CTX
*frame
= talloc_stackframe();
2588 struct tevent_context
*ev
;
2589 struct tevent_req
*req
;
2590 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2592 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2594 * Can't use sync call while an async call is in flight
2596 status
= NT_STATUS_INVALID_PARAMETER
;
2600 ev
= samba_tevent_context_init(frame
);
2605 req
= cli_tcon_andx_send(frame
, ev
, cli
, share
, dev
, pass
, passlen
);
2610 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2614 status
= cli_tcon_andx_recv(req
);
2620 struct cli_tree_connect_state
{
2621 struct cli_state
*cli
;
2624 static struct tevent_req
*cli_raw_tcon_send(
2625 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
, struct cli_state
*cli
,
2626 const char *service
, const char *pass
, const char *dev
);
2627 static NTSTATUS
cli_raw_tcon_recv(struct tevent_req
*req
,
2628 uint16
*max_xmit
, uint16
*tid
);
2630 static void cli_tree_connect_smb2_done(struct tevent_req
*subreq
);
2631 static void cli_tree_connect_andx_done(struct tevent_req
*subreq
);
2632 static void cli_tree_connect_raw_done(struct tevent_req
*subreq
);
2634 static struct tevent_req
*cli_tree_connect_send(
2635 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
, struct cli_state
*cli
,
2636 const char *share
, const char *dev
, const char *pass
, int passlen
)
2638 struct tevent_req
*req
, *subreq
;
2639 struct cli_tree_connect_state
*state
;
2641 req
= tevent_req_create(mem_ctx
, &state
,
2642 struct cli_tree_connect_state
);
2648 cli
->share
= talloc_strdup(cli
, share
);
2649 if (tevent_req_nomem(cli
->share
, req
)) {
2650 return tevent_req_post(req
, ev
);
2653 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2654 subreq
= smb2cli_tcon_send(state
, ev
, cli
, share
);
2655 if (tevent_req_nomem(subreq
, req
)) {
2656 return tevent_req_post(req
, ev
);
2658 tevent_req_set_callback(subreq
, cli_tree_connect_smb2_done
,
2663 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_LANMAN1
) {
2664 subreq
= cli_tcon_andx_send(state
, ev
, cli
, share
, dev
,
2666 if (tevent_req_nomem(subreq
, req
)) {
2667 return tevent_req_post(req
, ev
);
2669 tevent_req_set_callback(subreq
, cli_tree_connect_andx_done
,
2674 subreq
= cli_raw_tcon_send(state
, ev
, cli
, share
, pass
, dev
);
2675 if (tevent_req_nomem(subreq
, req
)) {
2676 return tevent_req_post(req
, ev
);
2678 tevent_req_set_callback(subreq
, cli_tree_connect_raw_done
, req
);
2683 static void cli_tree_connect_smb2_done(struct tevent_req
*subreq
)
2685 tevent_req_simple_finish_ntstatus(
2686 subreq
, smb2cli_tcon_recv(subreq
));
2689 static void cli_tree_connect_andx_done(struct tevent_req
*subreq
)
2691 tevent_req_simple_finish_ntstatus(
2692 subreq
, cli_tcon_andx_recv(subreq
));
2695 static void cli_tree_connect_raw_done(struct tevent_req
*subreq
)
2697 struct tevent_req
*req
= tevent_req_callback_data(
2698 subreq
, struct tevent_req
);
2699 struct cli_tree_connect_state
*state
= tevent_req_data(
2700 req
, struct cli_tree_connect_state
);
2702 uint16_t max_xmit
= 0;
2705 status
= cli_raw_tcon_recv(subreq
, &max_xmit
, &tid
);
2706 if (tevent_req_nterror(req
, status
)) {
2709 cli_state_set_tid(state
->cli
, tid
);
2710 tevent_req_done(req
);
2713 static NTSTATUS
cli_tree_connect_recv(struct tevent_req
*req
)
2715 return tevent_req_simple_recv_ntstatus(req
);
2718 NTSTATUS
cli_tree_connect(struct cli_state
*cli
, const char *share
,
2719 const char *dev
, const char *pass
, int passlen
)
2721 struct tevent_context
*ev
;
2722 struct tevent_req
*req
;
2723 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2725 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2726 return NT_STATUS_INVALID_PARAMETER
;
2728 ev
= samba_tevent_context_init(talloc_tos());
2732 req
= cli_tree_connect_send(ev
, ev
, cli
, share
, dev
, pass
, passlen
);
2736 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2739 status
= cli_tree_connect_recv(req
);
2745 /****************************************************************************
2746 Send a tree disconnect.
2747 ****************************************************************************/
2749 struct cli_tdis_state
{
2750 struct cli_state
*cli
;
2753 static void cli_tdis_done(struct tevent_req
*subreq
);
2755 static struct tevent_req
*cli_tdis_send(TALLOC_CTX
*mem_ctx
,
2756 struct tevent_context
*ev
,
2757 struct cli_state
*cli
)
2759 struct tevent_req
*req
, *subreq
;
2760 struct cli_tdis_state
*state
;
2762 req
= tevent_req_create(mem_ctx
, &state
, struct cli_tdis_state
);
2768 subreq
= cli_smb_send(state
, ev
, cli
, SMBtdis
, 0, 0, NULL
, 0, NULL
);
2769 if (tevent_req_nomem(subreq
, req
)) {
2770 return tevent_req_post(req
, ev
);
2772 tevent_req_set_callback(subreq
, cli_tdis_done
, req
);
2776 static void cli_tdis_done(struct tevent_req
*subreq
)
2778 struct tevent_req
*req
= tevent_req_callback_data(
2779 subreq
, struct tevent_req
);
2780 struct cli_tdis_state
*state
= tevent_req_data(
2781 req
, struct cli_tdis_state
);
2784 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2785 TALLOC_FREE(subreq
);
2786 if (!NT_STATUS_IS_OK(status
)) {
2787 tevent_req_nterror(req
, status
);
2790 cli_state_set_tid(state
->cli
, UINT16_MAX
);
2791 tevent_req_done(req
);
2794 static NTSTATUS
cli_tdis_recv(struct tevent_req
*req
)
2796 return tevent_req_simple_recv_ntstatus(req
);
2799 NTSTATUS
cli_tdis(struct cli_state
*cli
)
2801 struct tevent_context
*ev
;
2802 struct tevent_req
*req
;
2803 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2805 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2806 return NT_STATUS_INVALID_PARAMETER
;
2808 ev
= samba_tevent_context_init(talloc_tos());
2812 req
= cli_tdis_send(ev
, ev
, cli
);
2816 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2819 status
= cli_tdis_recv(req
);
2825 struct cli_connect_sock_state
{
2826 const char **called_names
;
2827 const char **calling_names
;
2833 static void cli_connect_sock_done(struct tevent_req
*subreq
);
2836 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2840 static struct tevent_req
*cli_connect_sock_send(
2841 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
2842 const char *host
, int name_type
, const struct sockaddr_storage
*pss
,
2843 const char *myname
, uint16_t port
)
2845 struct tevent_req
*req
, *subreq
;
2846 struct cli_connect_sock_state
*state
;
2848 unsigned i
, num_addrs
;
2851 req
= tevent_req_create(mem_ctx
, &state
,
2852 struct cli_connect_sock_state
);
2857 prog
= getenv("LIBSMB_PROG");
2859 state
->fd
= sock_exec(prog
);
2860 if (state
->fd
== -1) {
2861 status
= map_nt_error_from_unix(errno
);
2862 tevent_req_nterror(req
, status
);
2865 tevent_req_done(req
);
2867 return tevent_req_post(req
, ev
);
2870 if ((pss
== NULL
) || is_zero_addr(pss
)) {
2871 struct sockaddr_storage
*addrs
;
2874 * Here we cheat. resolve_name_list is not async at all. So
2875 * this call will only be really async if the name lookup has
2876 * been done externally.
2879 status
= resolve_name_list(state
, host
, name_type
,
2880 &addrs
, &num_addrs
);
2881 if (!NT_STATUS_IS_OK(status
)) {
2882 tevent_req_nterror(req
, status
);
2883 return tevent_req_post(req
, ev
);
2890 state
->called_names
= talloc_array(state
, const char *, num_addrs
);
2891 if (tevent_req_nomem(state
->called_names
, req
)) {
2892 return tevent_req_post(req
, ev
);
2894 state
->called_types
= talloc_array(state
, int, num_addrs
);
2895 if (tevent_req_nomem(state
->called_types
, req
)) {
2896 return tevent_req_post(req
, ev
);
2898 state
->calling_names
= talloc_array(state
, const char *, num_addrs
);
2899 if (tevent_req_nomem(state
->calling_names
, req
)) {
2900 return tevent_req_post(req
, ev
);
2902 for (i
=0; i
<num_addrs
; i
++) {
2903 state
->called_names
[i
] = host
;
2904 state
->called_types
[i
] = name_type
;
2905 state
->calling_names
[i
] = myname
;
2908 subreq
= smbsock_any_connect_send(
2909 state
, ev
, pss
, state
->called_names
, state
->called_types
,
2910 state
->calling_names
, NULL
, num_addrs
, port
);
2911 if (tevent_req_nomem(subreq
, req
)) {
2912 return tevent_req_post(req
, ev
);
2914 tevent_req_set_callback(subreq
, cli_connect_sock_done
, req
);
2918 static void cli_connect_sock_done(struct tevent_req
*subreq
)
2920 struct tevent_req
*req
= tevent_req_callback_data(
2921 subreq
, struct tevent_req
);
2922 struct cli_connect_sock_state
*state
= tevent_req_data(
2923 req
, struct cli_connect_sock_state
);
2926 status
= smbsock_any_connect_recv(subreq
, &state
->fd
, NULL
,
2928 TALLOC_FREE(subreq
);
2929 if (tevent_req_nterror(req
, status
)) {
2932 set_socket_options(state
->fd
, lp_socket_options());
2933 tevent_req_done(req
);
2936 static NTSTATUS
cli_connect_sock_recv(struct tevent_req
*req
,
2937 int *pfd
, uint16_t *pport
)
2939 struct cli_connect_sock_state
*state
= tevent_req_data(
2940 req
, struct cli_connect_sock_state
);
2943 if (tevent_req_is_nterror(req
, &status
)) {
2947 *pport
= state
->port
;
2948 return NT_STATUS_OK
;
2951 struct cli_connect_nb_state
{
2952 const char *desthost
;
2955 struct cli_state
*cli
;
2958 static void cli_connect_nb_done(struct tevent_req
*subreq
);
2960 static struct tevent_req
*cli_connect_nb_send(
2961 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
2962 const char *host
, const struct sockaddr_storage
*dest_ss
,
2963 uint16_t port
, int name_type
, const char *myname
,
2964 int signing_state
, int flags
)
2966 struct tevent_req
*req
, *subreq
;
2967 struct cli_connect_nb_state
*state
;
2970 req
= tevent_req_create(mem_ctx
, &state
, struct cli_connect_nb_state
);
2974 state
->desthost
= host
;
2975 state
->signing_state
= signing_state
;
2976 state
->flags
= flags
;
2978 p
= strchr(host
, '#');
2980 name_type
= strtol(p
+1, NULL
, 16);
2981 host
= talloc_strndup(state
, host
, p
- host
);
2982 if (tevent_req_nomem(host
, req
)) {
2983 return tevent_req_post(req
, ev
);
2987 subreq
= cli_connect_sock_send(state
, ev
, host
, name_type
, dest_ss
,
2989 if (tevent_req_nomem(subreq
, req
)) {
2990 return tevent_req_post(req
, ev
);
2992 tevent_req_set_callback(subreq
, cli_connect_nb_done
, req
);
2996 static void cli_connect_nb_done(struct tevent_req
*subreq
)
2998 struct tevent_req
*req
= tevent_req_callback_data(
2999 subreq
, struct tevent_req
);
3000 struct cli_connect_nb_state
*state
= tevent_req_data(
3001 req
, struct cli_connect_nb_state
);
3006 status
= cli_connect_sock_recv(subreq
, &fd
, &port
);
3007 TALLOC_FREE(subreq
);
3008 if (tevent_req_nterror(req
, status
)) {
3012 state
->cli
= cli_state_create(state
, fd
, state
->desthost
, NULL
,
3013 state
->signing_state
, state
->flags
);
3014 if (tevent_req_nomem(state
->cli
, req
)) {
3018 tevent_req_done(req
);
3021 static NTSTATUS
cli_connect_nb_recv(struct tevent_req
*req
,
3022 struct cli_state
**pcli
)
3024 struct cli_connect_nb_state
*state
= tevent_req_data(
3025 req
, struct cli_connect_nb_state
);
3028 if (tevent_req_is_nterror(req
, &status
)) {
3031 *pcli
= talloc_move(NULL
, &state
->cli
);
3032 return NT_STATUS_OK
;
3035 NTSTATUS
cli_connect_nb(const char *host
, const struct sockaddr_storage
*dest_ss
,
3036 uint16_t port
, int name_type
, const char *myname
,
3037 int signing_state
, int flags
, struct cli_state
**pcli
)
3039 struct tevent_context
*ev
;
3040 struct tevent_req
*req
;
3041 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3043 ev
= samba_tevent_context_init(talloc_tos());
3047 req
= cli_connect_nb_send(ev
, ev
, host
, dest_ss
, port
, name_type
,
3048 myname
, signing_state
, flags
);
3052 if (!tevent_req_set_endtime(req
, ev
, timeval_current_ofs(20, 0))) {
3055 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3058 status
= cli_connect_nb_recv(req
, pcli
);
3064 struct cli_start_connection_state
{
3065 struct tevent_context
*ev
;
3066 struct cli_state
*cli
;
3069 static void cli_start_connection_connected(struct tevent_req
*subreq
);
3070 static void cli_start_connection_done(struct tevent_req
*subreq
);
3073 establishes a connection to after the negprot.
3074 @param output_cli A fully initialised cli structure, non-null only on success
3075 @param dest_host The netbios name of the remote host
3076 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3077 @param port (optional) The destination port (0 for default)
3080 static struct tevent_req
*cli_start_connection_send(
3081 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
3082 const char *my_name
, const char *dest_host
,
3083 const struct sockaddr_storage
*dest_ss
, int port
,
3084 int signing_state
, int flags
)
3086 struct tevent_req
*req
, *subreq
;
3087 struct cli_start_connection_state
*state
;
3089 req
= tevent_req_create(mem_ctx
, &state
,
3090 struct cli_start_connection_state
);
3096 subreq
= cli_connect_nb_send(state
, ev
, dest_host
, dest_ss
, port
,
3097 0x20, my_name
, signing_state
, flags
);
3098 if (tevent_req_nomem(subreq
, req
)) {
3099 return tevent_req_post(req
, ev
);
3101 tevent_req_set_callback(subreq
, cli_start_connection_connected
, req
);
3105 static void cli_start_connection_connected(struct tevent_req
*subreq
)
3107 struct tevent_req
*req
= tevent_req_callback_data(
3108 subreq
, struct tevent_req
);
3109 struct cli_start_connection_state
*state
= tevent_req_data(
3110 req
, struct cli_start_connection_state
);
3113 status
= cli_connect_nb_recv(subreq
, &state
->cli
);
3114 TALLOC_FREE(subreq
);
3115 if (tevent_req_nterror(req
, status
)) {
3119 subreq
= smbXcli_negprot_send(state
, state
->ev
, state
->cli
->conn
,
3120 state
->cli
->timeout
,
3121 lp_cli_minprotocol(),
3122 lp_cli_maxprotocol());
3123 if (tevent_req_nomem(subreq
, req
)) {
3126 tevent_req_set_callback(subreq
, cli_start_connection_done
, req
);
3129 static void cli_start_connection_done(struct tevent_req
*subreq
)
3131 struct tevent_req
*req
= tevent_req_callback_data(
3132 subreq
, struct tevent_req
);
3133 struct cli_start_connection_state
*state
= tevent_req_data(
3134 req
, struct cli_start_connection_state
);
3137 status
= smbXcli_negprot_recv(subreq
);
3138 TALLOC_FREE(subreq
);
3139 if (tevent_req_nterror(req
, status
)) {
3143 if (smbXcli_conn_protocol(state
->cli
->conn
) >= PROTOCOL_SMB2_02
) {
3144 /* Ensure we ask for some initial credits. */
3145 smb2cli_conn_set_max_credits(state
->cli
->conn
,
3146 DEFAULT_SMB2_MAX_CREDITS
);
3149 tevent_req_done(req
);
3152 static NTSTATUS
cli_start_connection_recv(struct tevent_req
*req
,
3153 struct cli_state
**output_cli
)
3155 struct cli_start_connection_state
*state
= tevent_req_data(
3156 req
, struct cli_start_connection_state
);
3159 if (tevent_req_is_nterror(req
, &status
)) {
3162 *output_cli
= state
->cli
;
3164 return NT_STATUS_OK
;
3167 NTSTATUS
cli_start_connection(struct cli_state
**output_cli
,
3168 const char *my_name
,
3169 const char *dest_host
,
3170 const struct sockaddr_storage
*dest_ss
, int port
,
3171 int signing_state
, int flags
)
3173 struct tevent_context
*ev
;
3174 struct tevent_req
*req
;
3175 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3177 ev
= samba_tevent_context_init(talloc_tos());
3181 req
= cli_start_connection_send(ev
, ev
, my_name
, dest_host
, dest_ss
,
3182 port
, signing_state
, flags
);
3186 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3189 status
= cli_start_connection_recv(req
, output_cli
);
3196 establishes a connection right up to doing tconX, password specified.
3197 @param output_cli A fully initialised cli structure, non-null only on success
3198 @param dest_host The netbios name of the remote host
3199 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3200 @param port (optional) The destination port (0 for default)
3201 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3202 @param service_type The 'type' of serivice.
3203 @param user Username, unix string
3204 @param domain User's domain
3205 @param password User's password, unencrypted unix string.
3208 struct cli_full_connection_state
{
3209 struct tevent_context
*ev
;
3210 const char *service
;
3211 const char *service_type
;
3214 const char *password
;
3217 struct cli_state
*cli
;
3220 static int cli_full_connection_state_destructor(
3221 struct cli_full_connection_state
*s
);
3222 static void cli_full_connection_started(struct tevent_req
*subreq
);
3223 static void cli_full_connection_sess_set_up(struct tevent_req
*subreq
);
3224 static void cli_full_connection_done(struct tevent_req
*subreq
);
3226 struct tevent_req
*cli_full_connection_send(
3227 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
3228 const char *my_name
, const char *dest_host
,
3229 const struct sockaddr_storage
*dest_ss
, int port
,
3230 const char *service
, const char *service_type
,
3231 const char *user
, const char *domain
,
3232 const char *password
, int flags
, int signing_state
)
3234 struct tevent_req
*req
, *subreq
;
3235 struct cli_full_connection_state
*state
;
3237 req
= tevent_req_create(mem_ctx
, &state
,
3238 struct cli_full_connection_state
);
3242 talloc_set_destructor(state
, cli_full_connection_state_destructor
);
3245 state
->service
= service
;
3246 state
->service_type
= service_type
;
3248 state
->domain
= domain
;
3249 state
->password
= password
;
3250 state
->flags
= flags
;
3252 state
->pw_len
= state
->password
? strlen(state
->password
)+1 : 0;
3253 if (state
->password
== NULL
) {
3254 state
->password
= "";
3257 subreq
= cli_start_connection_send(
3258 state
, ev
, my_name
, dest_host
, dest_ss
, port
,
3259 signing_state
, flags
);
3260 if (tevent_req_nomem(subreq
, req
)) {
3261 return tevent_req_post(req
, ev
);
3263 tevent_req_set_callback(subreq
, cli_full_connection_started
, req
);
3267 static int cli_full_connection_state_destructor(
3268 struct cli_full_connection_state
*s
)
3270 if (s
->cli
!= NULL
) {
3271 cli_shutdown(s
->cli
);
3277 static void cli_full_connection_started(struct tevent_req
*subreq
)
3279 struct tevent_req
*req
= tevent_req_callback_data(
3280 subreq
, struct tevent_req
);
3281 struct cli_full_connection_state
*state
= tevent_req_data(
3282 req
, struct cli_full_connection_state
);
3285 status
= cli_start_connection_recv(subreq
, &state
->cli
);
3286 TALLOC_FREE(subreq
);
3287 if (tevent_req_nterror(req
, status
)) {
3290 subreq
= cli_session_setup_send(
3291 state
, state
->ev
, state
->cli
, state
->user
,
3292 state
->password
, state
->pw_len
, state
->password
, state
->pw_len
,
3294 if (tevent_req_nomem(subreq
, req
)) {
3297 tevent_req_set_callback(subreq
, cli_full_connection_sess_set_up
, req
);
3300 static void cli_full_connection_sess_set_up(struct tevent_req
*subreq
)
3302 struct tevent_req
*req
= tevent_req_callback_data(
3303 subreq
, struct tevent_req
);
3304 struct cli_full_connection_state
*state
= tevent_req_data(
3305 req
, struct cli_full_connection_state
);
3308 status
= cli_session_setup_recv(subreq
);
3309 TALLOC_FREE(subreq
);
3311 if (!NT_STATUS_IS_OK(status
) &&
3312 (state
->flags
& CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK
)) {
3314 state
->flags
&= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK
;
3316 subreq
= cli_session_setup_send(
3317 state
, state
->ev
, state
->cli
, "", "", 0, "", 0,
3319 if (tevent_req_nomem(subreq
, req
)) {
3322 tevent_req_set_callback(
3323 subreq
, cli_full_connection_sess_set_up
, req
);
3327 if (tevent_req_nterror(req
, status
)) {
3331 if (state
->service
!= NULL
) {
3332 subreq
= cli_tree_connect_send(
3333 state
, state
->ev
, state
->cli
,
3334 state
->service
, state
->service_type
,
3335 state
->password
, state
->pw_len
);
3336 if (tevent_req_nomem(subreq
, req
)) {
3339 tevent_req_set_callback(subreq
, cli_full_connection_done
, req
);
3343 status
= cli_init_creds(state
->cli
, state
->user
, state
->domain
,
3345 if (tevent_req_nterror(req
, status
)) {
3348 tevent_req_done(req
);
3351 static void cli_full_connection_done(struct tevent_req
*subreq
)
3353 struct tevent_req
*req
= tevent_req_callback_data(
3354 subreq
, struct tevent_req
);
3355 struct cli_full_connection_state
*state
= tevent_req_data(
3356 req
, struct cli_full_connection_state
);
3359 status
= cli_tree_connect_recv(subreq
);
3360 TALLOC_FREE(subreq
);
3361 if (tevent_req_nterror(req
, status
)) {
3364 status
= cli_init_creds(state
->cli
, state
->user
, state
->domain
,
3366 if (tevent_req_nterror(req
, status
)) {
3369 tevent_req_done(req
);
3372 NTSTATUS
cli_full_connection_recv(struct tevent_req
*req
,
3373 struct cli_state
**output_cli
)
3375 struct cli_full_connection_state
*state
= tevent_req_data(
3376 req
, struct cli_full_connection_state
);
3379 if (tevent_req_is_nterror(req
, &status
)) {
3382 *output_cli
= state
->cli
;
3383 talloc_set_destructor(state
, NULL
);
3384 return NT_STATUS_OK
;
3387 NTSTATUS
cli_full_connection(struct cli_state
**output_cli
,
3388 const char *my_name
,
3389 const char *dest_host
,
3390 const struct sockaddr_storage
*dest_ss
, int port
,
3391 const char *service
, const char *service_type
,
3392 const char *user
, const char *domain
,
3393 const char *password
, int flags
,
3396 struct tevent_context
*ev
;
3397 struct tevent_req
*req
;
3398 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3400 ev
= samba_tevent_context_init(talloc_tos());
3404 req
= cli_full_connection_send(
3405 ev
, ev
, my_name
, dest_host
, dest_ss
, port
, service
,
3406 service_type
, user
, domain
, password
, flags
, signing_state
);
3410 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3413 status
= cli_full_connection_recv(req
, output_cli
);
3419 /****************************************************************************
3420 Send an old style tcon.
3421 ****************************************************************************/
3422 struct cli_raw_tcon_state
{
3426 static void cli_raw_tcon_done(struct tevent_req
*subreq
);
3428 static struct tevent_req
*cli_raw_tcon_send(
3429 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
, struct cli_state
*cli
,
3430 const char *service
, const char *pass
, const char *dev
)
3432 struct tevent_req
*req
, *subreq
;
3433 struct cli_raw_tcon_state
*state
;
3436 req
= tevent_req_create(mem_ctx
, &state
, struct cli_raw_tcon_state
);
3441 if (!lp_client_plaintext_auth() && (*pass
)) {
3442 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3443 " or 'client ntlmv2 auth = yes'\n"));
3444 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3445 return tevent_req_post(req
, ev
);
3448 bytes
= talloc_array(state
, uint8_t, 0);
3449 bytes
= smb_bytes_push_bytes(bytes
, 4, NULL
, 0);
3450 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
),
3451 service
, strlen(service
)+1, NULL
);
3452 bytes
= smb_bytes_push_bytes(bytes
, 4, NULL
, 0);
3453 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
),
3454 pass
, strlen(pass
)+1, NULL
);
3455 bytes
= smb_bytes_push_bytes(bytes
, 4, NULL
, 0);
3456 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
),
3457 dev
, strlen(dev
)+1, NULL
);
3459 if (tevent_req_nomem(bytes
, req
)) {
3460 return tevent_req_post(req
, ev
);
3463 subreq
= cli_smb_send(state
, ev
, cli
, SMBtcon
, 0, 0, NULL
,
3464 talloc_get_size(bytes
), bytes
);
3465 if (tevent_req_nomem(subreq
, req
)) {
3466 return tevent_req_post(req
, ev
);
3468 tevent_req_set_callback(subreq
, cli_raw_tcon_done
, req
);
3472 static void cli_raw_tcon_done(struct tevent_req
*subreq
)
3474 struct tevent_req
*req
= tevent_req_callback_data(
3475 subreq
, struct tevent_req
);
3476 struct cli_raw_tcon_state
*state
= tevent_req_data(
3477 req
, struct cli_raw_tcon_state
);
3480 status
= cli_smb_recv(subreq
, state
, NULL
, 2, NULL
, &state
->ret_vwv
,
3482 TALLOC_FREE(subreq
);
3483 if (tevent_req_nterror(req
, status
)) {
3486 tevent_req_done(req
);
3489 static NTSTATUS
cli_raw_tcon_recv(struct tevent_req
*req
,
3490 uint16
*max_xmit
, uint16
*tid
)
3492 struct cli_raw_tcon_state
*state
= tevent_req_data(
3493 req
, struct cli_raw_tcon_state
);
3496 if (tevent_req_is_nterror(req
, &status
)) {
3499 *max_xmit
= SVAL(state
->ret_vwv
+ 0, 0);
3500 *tid
= SVAL(state
->ret_vwv
+ 1, 0);
3501 return NT_STATUS_OK
;
3504 NTSTATUS
cli_raw_tcon(struct cli_state
*cli
,
3505 const char *service
, const char *pass
, const char *dev
,
3506 uint16
*max_xmit
, uint16
*tid
)
3508 struct tevent_context
*ev
;
3509 struct tevent_req
*req
;
3510 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3512 ev
= samba_tevent_context_init(talloc_tos());
3516 req
= cli_raw_tcon_send(ev
, ev
, cli
, service
, pass
, dev
);
3520 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3523 status
= cli_raw_tcon_recv(req
, max_xmit
, tid
);
3529 /* Return a cli_state pointing at the IPC$ share for the given server */
3531 struct cli_state
*get_ipc_connect(char *server
,
3532 struct sockaddr_storage
*server_ss
,
3533 const struct user_auth_info
*user_info
)
3535 struct cli_state
*cli
;
3537 uint32_t flags
= CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK
;
3539 if (user_info
->use_kerberos
) {
3540 flags
|= CLI_FULL_CONNECTION_USE_KERBEROS
;
3543 nt_status
= cli_full_connection(&cli
, NULL
, server
, server_ss
, 0, "IPC$", "IPC",
3544 user_info
->username
? user_info
->username
: "",
3546 user_info
->password
? user_info
->password
: "",
3548 SMB_SIGNING_DEFAULT
);
3550 if (NT_STATUS_IS_OK(nt_status
)) {
3552 } else if (is_ipaddress(server
)) {
3553 /* windows 9* needs a correct NMB name for connections */
3554 fstring remote_name
;
3556 if (name_status_find("*", 0, 0, server_ss
, remote_name
)) {
3557 cli
= get_ipc_connect(remote_name
, server_ss
, user_info
);
3566 * Given the IP address of a master browser on the network, return its
3567 * workgroup and connect to it.
3569 * This function is provided to allow additional processing beyond what
3570 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3571 * browsers and obtain each master browsers' list of domains (in case the
3572 * first master browser is recently on the network and has not yet
3573 * synchronized with other master browsers and therefore does not yet have the
3574 * entire network browse list)
3577 struct cli_state
*get_ipc_connect_master_ip(TALLOC_CTX
*ctx
,
3578 struct sockaddr_storage
*mb_ip
,
3579 const struct user_auth_info
*user_info
,
3580 char **pp_workgroup_out
)
3582 char addr
[INET6_ADDRSTRLEN
];
3584 struct cli_state
*cli
;
3585 struct sockaddr_storage server_ss
;
3587 *pp_workgroup_out
= NULL
;
3589 print_sockaddr(addr
, sizeof(addr
), mb_ip
);
3590 DEBUG(99, ("Looking up name of master browser %s\n",
3594 * Do a name status query to find out the name of the master browser.
3595 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3596 * master browser will not respond to a wildcard query (or, at least,
3597 * an NT4 server acting as the domain master browser will not).
3599 * We might be able to use ONLY the query on MSBROWSE, but that's not
3600 * yet been tested with all Windows versions, so until it is, leave
3601 * the original wildcard query as the first choice and fall back to
3602 * MSBROWSE if the wildcard query fails.
3604 if (!name_status_find("*", 0, 0x1d, mb_ip
, name
) &&
3605 !name_status_find(MSBROWSE
, 1, 0x1d, mb_ip
, name
)) {
3607 DEBUG(99, ("Could not retrieve name status for %s\n",
3612 if (!find_master_ip(name
, &server_ss
)) {
3613 DEBUG(99, ("Could not find master ip for %s\n", name
));
3617 *pp_workgroup_out
= talloc_strdup(ctx
, name
);
3619 DEBUG(4, ("found master browser %s, %s\n", name
, addr
));
3621 print_sockaddr(addr
, sizeof(addr
), &server_ss
);
3622 cli
= get_ipc_connect(addr
, &server_ss
, user_info
);
3628 * Return the IP address and workgroup of a master browser on the network, and
3632 struct cli_state
*get_ipc_connect_master_ip_bcast(TALLOC_CTX
*ctx
,
3633 const struct user_auth_info
*user_info
,
3634 char **pp_workgroup_out
)
3636 struct sockaddr_storage
*ip_list
;
3637 struct cli_state
*cli
;
3641 *pp_workgroup_out
= NULL
;
3643 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3645 /* Go looking for workgroups by broadcasting on the local network */
3647 status
= name_resolve_bcast(MSBROWSE
, 1, talloc_tos(),
3649 if (!NT_STATUS_IS_OK(status
)) {
3650 DEBUG(99, ("No master browsers responded: %s\n",
3651 nt_errstr(status
)));
3655 for (i
= 0; i
< count
; i
++) {
3656 char addr
[INET6_ADDRSTRLEN
];
3657 print_sockaddr(addr
, sizeof(addr
), &ip_list
[i
]);
3658 DEBUG(99, ("Found master browser %s\n", addr
));
3660 cli
= get_ipc_connect_master_ip(ctx
, &ip_list
[i
],
3661 user_info
, pp_workgroup_out
);