2 Unix SMB/CIFS implementation.
3 client connect/disconnect routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Andrew Bartlett 2001-2003
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "popt_common.h"
23 #include "../libcli/auth/libcli_auth.h"
24 #include "../libcli/auth/spnego.h"
26 #include "../libcli/auth/ntlmssp.h"
27 #include "libads/kerberos_proto.h"
29 #include "async_smb.h"
30 #include "libsmb/nmblib.h"
36 {PROTOCOL_CORE
, "PC NETWORK PROGRAM 1.0"},
37 {PROTOCOL_COREPLUS
, "MICROSOFT NETWORKS 1.03"},
38 {PROTOCOL_LANMAN1
, "MICROSOFT NETWORKS 3.0"},
39 {PROTOCOL_LANMAN1
, "LANMAN1.0"},
40 {PROTOCOL_LANMAN2
, "LM1.2X002"},
41 {PROTOCOL_LANMAN2
, "DOS LANMAN2.1"},
42 {PROTOCOL_LANMAN2
, "LANMAN2.1"},
43 {PROTOCOL_LANMAN2
, "Samba"},
44 {PROTOCOL_NT1
, "NT LANMAN 1.0"},
45 {PROTOCOL_NT1
, "NT LM 0.12"},
48 #define STAR_SMBSERVER "*SMBSERVER"
50 /********************************************************
51 Utility function to ensure we always return at least
52 a valid char * pointer to an empty string for the
53 cli->server_os, cli->server_type and cli->server_domain
55 *******************************************************/
57 static NTSTATUS
smb_bytes_talloc_string(struct cli_state
*cli
,
64 *destlen
= clistr_pull_talloc(cli
,
66 SVAL(inbuf
, smb_flg2
),
72 return NT_STATUS_NO_MEMORY
;
76 *dest
= talloc_strdup(cli
, "");
78 return NT_STATUS_NO_MEMORY
;
85 * Set the user session key for a connection
86 * @param cli The cli structure to add it too
87 * @param session_key The session key used. (A copy of this is taken for the cli struct)
91 static void cli_set_session_key (struct cli_state
*cli
, const DATA_BLOB session_key
)
93 cli
->user_session_key
= data_blob(session_key
.data
, session_key
.length
);
96 /****************************************************************************
97 Do an old lanman2 style session setup.
98 ****************************************************************************/
100 struct cli_session_setup_lanman2_state
{
101 struct cli_state
*cli
;
106 static void cli_session_setup_lanman2_done(struct tevent_req
*subreq
);
108 static struct tevent_req
*cli_session_setup_lanman2_send(
109 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
110 struct cli_state
*cli
, const char *user
,
111 const char *pass
, size_t passlen
,
112 const char *workgroup
)
114 struct tevent_req
*req
, *subreq
;
115 struct cli_session_setup_lanman2_state
*state
;
116 DATA_BLOB lm_response
= data_blob_null
;
121 req
= tevent_req_create(mem_ctx
, &state
,
122 struct cli_session_setup_lanman2_state
);
131 * LANMAN servers predate NT status codes and Unicode and
132 * ignore those smb flags so we must disable the corresponding
133 * default capabilities that would otherwise cause the Unicode
134 * and NT Status flags to be set (and even returned by the
138 cli
->capabilities
&= ~(CAP_UNICODE
| CAP_STATUS32
);
141 * if in share level security then don't send a password now
143 if (!(cli
->sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
)) {
148 && (cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
)
151 * Encrypted mode needed, and non encrypted password
154 lm_response
= data_blob(NULL
, 24);
155 if (tevent_req_nomem(lm_response
.data
, req
)) {
156 return tevent_req_post(req
, ev
);
159 if (!SMBencrypt(pass
, cli
->secblob
.data
,
160 (uint8_t *)lm_response
.data
)) {
161 DEBUG(1, ("Password is > 14 chars in length, and is "
162 "therefore incompatible with Lanman "
163 "authentication\n"));
164 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
165 return tevent_req_post(req
, ev
);
167 } else if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
)
170 * Encrypted mode needed, and encrypted password
173 lm_response
= data_blob(pass
, passlen
);
174 if (tevent_req_nomem(lm_response
.data
, req
)) {
175 return tevent_req_post(req
, ev
);
177 } else if (passlen
> 0) {
179 size_t converted_size
;
181 * Plaintext mode needed, assume plaintext supplied.
183 buf
= talloc_array(talloc_tos(), uint8_t, 0);
184 buf
= smb_bytes_push_str(buf
, cli_ucs2(cli
), pass
, passlen
+1,
186 if (tevent_req_nomem(buf
, req
)) {
187 return tevent_req_post(req
, ev
);
189 lm_response
= data_blob(pass
, passlen
);
191 if (tevent_req_nomem(lm_response
.data
, req
)) {
192 return tevent_req_post(req
, ev
);
196 SCVAL(vwv
+0, 0, 0xff);
199 SSVAL(vwv
+2, 0, CLI_BUFFER_SIZE
);
202 SIVAL(vwv
+5, 0, cli
->sesskey
);
203 SSVAL(vwv
+7, 0, lm_response
.length
);
205 bytes
= talloc_array(state
, uint8_t, lm_response
.length
);
206 if (tevent_req_nomem(bytes
, req
)) {
207 return tevent_req_post(req
, ev
);
209 if (lm_response
.length
!= 0) {
210 memcpy(bytes
, lm_response
.data
, lm_response
.length
);
212 data_blob_free(&lm_response
);
214 tmp
= talloc_strdup_upper(talloc_tos(), user
);
215 if (tevent_req_nomem(tmp
, req
)) {
216 return tevent_req_post(req
, ev
);
218 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), tmp
, strlen(tmp
)+1,
222 tmp
= talloc_strdup_upper(talloc_tos(), workgroup
);
223 if (tevent_req_nomem(tmp
, req
)) {
224 return tevent_req_post(req
, ev
);
226 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), tmp
, strlen(tmp
)+1,
228 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "Unix", 5, NULL
);
229 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "Samba", 6, NULL
);
231 if (tevent_req_nomem(bytes
, req
)) {
232 return tevent_req_post(req
, ev
);
235 subreq
= cli_smb_send(state
, ev
, cli
, SMBsesssetupX
, 0, 10, vwv
,
236 talloc_get_size(bytes
), bytes
);
237 if (tevent_req_nomem(subreq
, req
)) {
238 return tevent_req_post(req
, ev
);
240 tevent_req_set_callback(subreq
, cli_session_setup_lanman2_done
, req
);
244 static void cli_session_setup_lanman2_done(struct tevent_req
*subreq
)
246 struct tevent_req
*req
= tevent_req_callback_data(
247 subreq
, struct tevent_req
);
248 struct cli_session_setup_lanman2_state
*state
= tevent_req_data(
249 req
, struct cli_session_setup_lanman2_state
);
250 struct cli_state
*cli
= state
->cli
;
259 status
= cli_smb_recv(subreq
, state
, &in
, 0, NULL
, NULL
,
262 if (!NT_STATUS_IS_OK(status
)) {
263 tevent_req_nterror(req
, status
);
270 cli
->vuid
= SVAL(inbuf
, smb_uid
);
272 status
= smb_bytes_talloc_string(cli
,
279 if (!NT_STATUS_IS_OK(status
)) {
280 tevent_req_nterror(req
, status
);
285 status
= smb_bytes_talloc_string(cli
,
292 if (!NT_STATUS_IS_OK(status
)) {
293 tevent_req_nterror(req
, status
);
298 status
= smb_bytes_talloc_string(cli
,
305 if (!NT_STATUS_IS_OK(status
)) {
306 tevent_req_nterror(req
, status
);
311 if (strstr(cli
->server_type
, "Samba")) {
312 cli
->is_samba
= True
;
314 status
= cli_set_username(cli
, state
->user
);
315 if (tevent_req_nterror(req
, status
)) {
318 tevent_req_done(req
);
321 static NTSTATUS
cli_session_setup_lanman2_recv(struct tevent_req
*req
)
323 return tevent_req_simple_recv_ntstatus(req
);
326 static NTSTATUS
cli_session_setup_lanman2(struct cli_state
*cli
, const char *user
,
327 const char *pass
, size_t passlen
,
328 const char *workgroup
)
330 TALLOC_CTX
*frame
= talloc_stackframe();
331 struct event_context
*ev
;
332 struct tevent_req
*req
;
333 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
335 if (cli_has_async_calls(cli
)) {
337 * Can't use sync call while an async call is in flight
339 status
= NT_STATUS_INVALID_PARAMETER
;
342 ev
= event_context_init(frame
);
346 req
= cli_session_setup_lanman2_send(frame
, ev
, cli
, user
, pass
, passlen
,
351 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
354 status
= cli_session_setup_lanman2_recv(req
);
357 if (!NT_STATUS_IS_OK(status
)) {
358 cli_set_error(cli
, status
);
363 /****************************************************************************
364 Work out suitable capabilities to offer the server.
365 ****************************************************************************/
367 static uint32
cli_session_setup_capabilities(struct cli_state
*cli
)
369 uint32 capabilities
= CAP_NT_SMBS
;
371 if (!cli
->force_dos_errors
)
372 capabilities
|= CAP_STATUS32
;
374 if (cli
->use_level_II_oplocks
)
375 capabilities
|= CAP_LEVEL_II_OPLOCKS
;
377 capabilities
|= (cli
->capabilities
& (CAP_UNICODE
|CAP_LARGE_FILES
|CAP_LARGE_READX
|CAP_LARGE_WRITEX
|CAP_DFS
));
381 /****************************************************************************
382 Do a NT1 guest session setup.
383 ****************************************************************************/
385 struct cli_session_setup_guest_state
{
386 struct cli_state
*cli
;
391 static void cli_session_setup_guest_done(struct tevent_req
*subreq
);
393 struct tevent_req
*cli_session_setup_guest_create(TALLOC_CTX
*mem_ctx
,
394 struct event_context
*ev
,
395 struct cli_state
*cli
,
396 struct tevent_req
**psmbreq
)
398 struct tevent_req
*req
, *subreq
;
399 struct cli_session_setup_guest_state
*state
;
403 req
= tevent_req_create(mem_ctx
, &state
,
404 struct cli_session_setup_guest_state
);
411 SCVAL(vwv
+0, 0, 0xFF);
414 SSVAL(vwv
+2, 0, CLI_BUFFER_SIZE
);
416 SSVAL(vwv
+4, 0, cli
->pid
);
417 SIVAL(vwv
+5, 0, cli
->sesskey
);
422 SIVAL(vwv
+11, 0, cli_session_setup_capabilities(cli
));
424 bytes
= talloc_array(state
, uint8_t, 0);
426 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "", 1, /* username */
428 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "", 1, /* workgroup */
430 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "Unix", 5, NULL
);
431 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "Samba", 6, NULL
);
438 state
->bytes
.iov_base
= (void *)bytes
;
439 state
->bytes
.iov_len
= talloc_get_size(bytes
);
441 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBsesssetupX
, 0, 13, vwv
,
443 if (subreq
== NULL
) {
447 tevent_req_set_callback(subreq
, cli_session_setup_guest_done
, req
);
452 struct tevent_req
*cli_session_setup_guest_send(TALLOC_CTX
*mem_ctx
,
453 struct event_context
*ev
,
454 struct cli_state
*cli
)
456 struct tevent_req
*req
, *subreq
;
459 req
= cli_session_setup_guest_create(mem_ctx
, ev
, cli
, &subreq
);
464 status
= cli_smb_req_send(subreq
);
465 if (NT_STATUS_IS_OK(status
)) {
466 tevent_req_nterror(req
, status
);
467 return tevent_req_post(req
, ev
);
472 static void cli_session_setup_guest_done(struct tevent_req
*subreq
)
474 struct tevent_req
*req
= tevent_req_callback_data(
475 subreq
, struct tevent_req
);
476 struct cli_session_setup_guest_state
*state
= tevent_req_data(
477 req
, struct cli_session_setup_guest_state
);
478 struct cli_state
*cli
= state
->cli
;
487 status
= cli_smb_recv(subreq
, state
, &in
, 0, NULL
, NULL
,
490 if (!NT_STATUS_IS_OK(status
)) {
491 tevent_req_nterror(req
, status
);
498 cli
->vuid
= SVAL(inbuf
, smb_uid
);
500 status
= smb_bytes_talloc_string(cli
,
507 if (!NT_STATUS_IS_OK(status
)) {
508 tevent_req_nterror(req
, status
);
513 status
= smb_bytes_talloc_string(cli
,
520 if (!NT_STATUS_IS_OK(status
)) {
521 tevent_req_nterror(req
, status
);
526 status
= smb_bytes_talloc_string(cli
,
533 if (!NT_STATUS_IS_OK(status
)) {
534 tevent_req_nterror(req
, status
);
539 if (strstr(cli
->server_type
, "Samba")) {
540 cli
->is_samba
= True
;
543 status
= cli_set_username(cli
, "");
544 if (!NT_STATUS_IS_OK(status
)) {
545 tevent_req_nterror(req
, status
);
548 tevent_req_done(req
);
551 NTSTATUS
cli_session_setup_guest_recv(struct tevent_req
*req
)
553 return tevent_req_simple_recv_ntstatus(req
);
556 static NTSTATUS
cli_session_setup_guest(struct cli_state
*cli
)
558 TALLOC_CTX
*frame
= talloc_stackframe();
559 struct event_context
*ev
;
560 struct tevent_req
*req
;
561 NTSTATUS status
= NT_STATUS_OK
;
563 if (cli_has_async_calls(cli
)) {
565 * Can't use sync call while an async call is in flight
567 status
= NT_STATUS_INVALID_PARAMETER
;
571 ev
= event_context_init(frame
);
573 status
= NT_STATUS_NO_MEMORY
;
577 req
= cli_session_setup_guest_send(frame
, ev
, cli
);
579 status
= NT_STATUS_NO_MEMORY
;
583 if (!tevent_req_poll(req
, ev
)) {
584 status
= map_nt_error_from_unix(errno
);
588 status
= cli_session_setup_guest_recv(req
);
591 if (!NT_STATUS_IS_OK(status
)) {
592 cli_set_error(cli
, status
);
597 /****************************************************************************
598 Do a NT1 plaintext session setup.
599 ****************************************************************************/
601 struct cli_session_setup_plain_state
{
602 struct cli_state
*cli
;
607 static void cli_session_setup_plain_done(struct tevent_req
*subreq
);
609 static struct tevent_req
*cli_session_setup_plain_send(
610 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
611 struct cli_state
*cli
,
612 const char *user
, const char *pass
, const char *workgroup
)
614 struct tevent_req
*req
, *subreq
;
615 struct cli_session_setup_plain_state
*state
;
621 req
= tevent_req_create(mem_ctx
, &state
,
622 struct cli_session_setup_plain_state
);
630 SCVAL(vwv
+0, 0, 0xff);
633 SSVAL(vwv
+2, 0, CLI_BUFFER_SIZE
);
635 SSVAL(vwv
+4, 0, cli
->pid
);
636 SIVAL(vwv
+5, 0, cli
->sesskey
);
641 SIVAL(vwv
+11, 0, cli_session_setup_capabilities(cli
));
643 bytes
= talloc_array(state
, uint8_t, 0);
644 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), pass
, strlen(pass
)+1,
646 if (tevent_req_nomem(bytes
, req
)) {
647 return tevent_req_post(req
, ev
);
649 SSVAL(vwv
+ (cli_ucs2(cli
) ? 8 : 7), 0, passlen
);
651 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
652 user
, strlen(user
)+1, NULL
);
653 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
654 workgroup
, strlen(workgroup
)+1, NULL
);
655 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
658 version
= talloc_asprintf(talloc_tos(), "Samba %s",
659 samba_version_string());
660 if (tevent_req_nomem(version
, req
)){
661 return tevent_req_post(req
, ev
);
663 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
664 version
, strlen(version
)+1, NULL
);
665 TALLOC_FREE(version
);
667 if (tevent_req_nomem(bytes
, req
)) {
668 return tevent_req_post(req
, ev
);
671 subreq
= cli_smb_send(state
, ev
, cli
, SMBsesssetupX
, 0, 13, vwv
,
672 talloc_get_size(bytes
), bytes
);
673 if (tevent_req_nomem(subreq
, req
)) {
674 return tevent_req_post(req
, ev
);
676 tevent_req_set_callback(subreq
, cli_session_setup_plain_done
, req
);
680 static void cli_session_setup_plain_done(struct tevent_req
*subreq
)
682 struct tevent_req
*req
= tevent_req_callback_data(
683 subreq
, struct tevent_req
);
684 struct cli_session_setup_plain_state
*state
= tevent_req_data(
685 req
, struct cli_session_setup_plain_state
);
686 struct cli_state
*cli
= state
->cli
;
695 status
= cli_smb_recv(subreq
, state
, &in
, 0, NULL
, NULL
,
698 if (tevent_req_nterror(req
, status
)) {
705 cli
->vuid
= SVAL(inbuf
, smb_uid
);
707 status
= smb_bytes_talloc_string(cli
,
714 if (!NT_STATUS_IS_OK(status
)) {
715 tevent_req_nterror(req
, status
);
720 status
= smb_bytes_talloc_string(cli
,
727 if (!NT_STATUS_IS_OK(status
)) {
728 tevent_req_nterror(req
, status
);
733 status
= smb_bytes_talloc_string(cli
,
740 if (!NT_STATUS_IS_OK(status
)) {
741 tevent_req_nterror(req
, status
);
746 status
= cli_set_username(cli
, state
->user
);
747 if (tevent_req_nterror(req
, status
)) {
750 if (strstr(cli
->server_type
, "Samba")) {
751 cli
->is_samba
= True
;
753 tevent_req_done(req
);
756 static NTSTATUS
cli_session_setup_plain_recv(struct tevent_req
*req
)
758 return tevent_req_simple_recv_ntstatus(req
);
761 static NTSTATUS
cli_session_setup_plain(struct cli_state
*cli
,
762 const char *user
, const char *pass
,
763 const char *workgroup
)
765 TALLOC_CTX
*frame
= talloc_stackframe();
766 struct event_context
*ev
;
767 struct tevent_req
*req
;
768 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
770 if (cli_has_async_calls(cli
)) {
772 * Can't use sync call while an async call is in flight
774 status
= NT_STATUS_INVALID_PARAMETER
;
777 ev
= event_context_init(frame
);
781 req
= cli_session_setup_plain_send(frame
, ev
, cli
, user
, pass
,
786 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
789 status
= cli_session_setup_plain_recv(req
);
792 if (!NT_STATUS_IS_OK(status
)) {
793 cli_set_error(cli
, status
);
798 /****************************************************************************
799 do a NT1 NTLM/LM encrypted session setup - for when extended security
801 @param cli client state to create do session setup on
803 @param pass *either* cleartext password (passlen !=24) or LM response.
804 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
805 @param workgroup The user's domain.
806 ****************************************************************************/
808 struct cli_session_setup_nt1_state
{
809 struct cli_state
*cli
;
812 DATA_BLOB session_key
;
816 static void cli_session_setup_nt1_done(struct tevent_req
*subreq
);
818 static struct tevent_req
*cli_session_setup_nt1_send(
819 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
820 struct cli_state
*cli
, const char *user
,
821 const char *pass
, size_t passlen
,
822 const char *ntpass
, size_t ntpasslen
,
823 const char *workgroup
)
825 struct tevent_req
*req
, *subreq
;
826 struct cli_session_setup_nt1_state
*state
;
827 DATA_BLOB lm_response
= data_blob_null
;
828 DATA_BLOB nt_response
= data_blob_null
;
829 DATA_BLOB session_key
= data_blob_null
;
832 char *workgroup_upper
;
834 req
= tevent_req_create(mem_ctx
, &state
,
835 struct cli_session_setup_nt1_state
);
844 /* do nothing - guest login */
845 } else if (passlen
!= 24) {
846 if (lp_client_ntlmv2_auth()) {
847 DATA_BLOB server_chal
;
848 DATA_BLOB names_blob
;
850 server_chal
= data_blob(cli
->secblob
.data
,
851 MIN(cli
->secblob
.length
, 8));
852 if (tevent_req_nomem(server_chal
.data
, req
)) {
853 return tevent_req_post(req
, ev
);
857 * note that the 'workgroup' here is a best
858 * guess - we don't know the server's domain
859 * at this point. The 'server name' is also
862 names_blob
= NTLMv2_generate_names_blob(
863 NULL
, cli
->called
.name
, workgroup
);
865 if (tevent_req_nomem(names_blob
.data
, req
)) {
866 return tevent_req_post(req
, ev
);
869 if (!SMBNTLMv2encrypt(NULL
, user
, workgroup
, pass
,
870 &server_chal
, &names_blob
,
871 &lm_response
, &nt_response
,
872 NULL
, &session_key
)) {
873 data_blob_free(&names_blob
);
874 data_blob_free(&server_chal
);
876 req
, NT_STATUS_ACCESS_DENIED
);
877 return tevent_req_post(req
, ev
);
879 data_blob_free(&names_blob
);
880 data_blob_free(&server_chal
);
884 E_md4hash(pass
, nt_hash
);
887 nt_response
= data_blob_null
;
889 nt_response
= data_blob(NULL
, 24);
890 if (tevent_req_nomem(nt_response
.data
, req
)) {
891 return tevent_req_post(req
, ev
);
894 SMBNTencrypt(pass
, cli
->secblob
.data
,
897 /* non encrypted password supplied. Ignore ntpass. */
898 if (lp_client_lanman_auth()) {
900 lm_response
= data_blob(NULL
, 24);
901 if (tevent_req_nomem(lm_response
.data
, req
)) {
902 return tevent_req_post(req
, ev
);
905 if (!SMBencrypt(pass
,cli
->secblob
.data
,
908 * Oops, the LM response is
909 * invalid, just put the NT
910 * response there instead
912 data_blob_free(&lm_response
);
913 lm_response
= data_blob(
919 * LM disabled, place NT# in LM field
922 lm_response
= data_blob(
923 nt_response
.data
, nt_response
.length
);
926 if (tevent_req_nomem(lm_response
.data
, req
)) {
927 return tevent_req_post(req
, ev
);
930 session_key
= data_blob(NULL
, 16);
931 if (tevent_req_nomem(session_key
.data
, req
)) {
932 return tevent_req_post(req
, ev
);
935 E_deshash(pass
, session_key
.data
);
936 memset(&session_key
.data
[8], '\0', 8);
938 SMBsesskeygen_ntv1(nt_hash
, session_key
.data
);
941 cli_temp_set_signing(cli
);
943 /* pre-encrypted password supplied. Only used for
944 security=server, can't do
945 signing because we don't have original key */
947 lm_response
= data_blob(pass
, passlen
);
948 if (tevent_req_nomem(lm_response
.data
, req
)) {
949 return tevent_req_post(req
, ev
);
952 nt_response
= data_blob(ntpass
, ntpasslen
);
953 if (tevent_req_nomem(nt_response
.data
, req
)) {
954 return tevent_req_post(req
, ev
);
959 state
->response
= data_blob_talloc(
960 state
, lm_response
.data
, lm_response
.length
);
962 state
->response
= data_blob_talloc(
963 state
, nt_response
.data
, nt_response
.length
);
965 if (tevent_req_nomem(state
->response
.data
, req
)) {
966 return tevent_req_post(req
, ev
);
969 if (session_key
.data
) {
970 state
->session_key
= data_blob_talloc(
971 state
, session_key
.data
, session_key
.length
);
972 if (tevent_req_nomem(state
->session_key
.data
, req
)) {
973 return tevent_req_post(req
, ev
);
976 data_blob_free(&session_key
);
978 SCVAL(vwv
+0, 0, 0xff);
981 SSVAL(vwv
+2, 0, CLI_BUFFER_SIZE
);
983 SSVAL(vwv
+4, 0, cli
->pid
);
984 SIVAL(vwv
+5, 0, cli
->sesskey
);
985 SSVAL(vwv
+7, 0, lm_response
.length
);
986 SSVAL(vwv
+8, 0, nt_response
.length
);
989 SIVAL(vwv
+11, 0, cli_session_setup_capabilities(cli
));
991 bytes
= talloc_array(state
, uint8_t,
992 lm_response
.length
+ nt_response
.length
);
993 if (tevent_req_nomem(bytes
, req
)) {
994 return tevent_req_post(req
, ev
);
996 if (lm_response
.length
!= 0) {
997 memcpy(bytes
, lm_response
.data
, lm_response
.length
);
999 if (nt_response
.length
!= 0) {
1000 memcpy(bytes
+ lm_response
.length
,
1001 nt_response
.data
, nt_response
.length
);
1003 data_blob_free(&lm_response
);
1004 data_blob_free(&nt_response
);
1006 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
1007 user
, strlen(user
)+1, NULL
);
1010 * Upper case here might help some NTLMv2 implementations
1012 workgroup_upper
= talloc_strdup_upper(talloc_tos(), workgroup
);
1013 if (tevent_req_nomem(workgroup_upper
, req
)) {
1014 return tevent_req_post(req
, ev
);
1016 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
1017 workgroup_upper
, strlen(workgroup_upper
)+1,
1019 TALLOC_FREE(workgroup_upper
);
1021 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "Unix", 5, NULL
);
1022 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "Samba", 6, NULL
);
1023 if (tevent_req_nomem(bytes
, req
)) {
1024 return tevent_req_post(req
, ev
);
1027 subreq
= cli_smb_send(state
, ev
, cli
, SMBsesssetupX
, 0, 13, vwv
,
1028 talloc_get_size(bytes
), bytes
);
1029 if (tevent_req_nomem(subreq
, req
)) {
1030 return tevent_req_post(req
, ev
);
1032 tevent_req_set_callback(subreq
, cli_session_setup_nt1_done
, req
);
1036 static void cli_session_setup_nt1_done(struct tevent_req
*subreq
)
1038 struct tevent_req
*req
= tevent_req_callback_data(
1039 subreq
, struct tevent_req
);
1040 struct cli_session_setup_nt1_state
*state
= tevent_req_data(
1041 req
, struct cli_session_setup_nt1_state
);
1042 struct cli_state
*cli
= state
->cli
;
1051 status
= cli_smb_recv(subreq
, state
, &in
, 0, NULL
, NULL
,
1052 &num_bytes
, &bytes
);
1053 TALLOC_FREE(subreq
);
1054 if (!NT_STATUS_IS_OK(status
)) {
1055 tevent_req_nterror(req
, status
);
1062 cli
->vuid
= SVAL(inbuf
, smb_uid
);
1064 status
= smb_bytes_talloc_string(cli
,
1070 if (!NT_STATUS_IS_OK(status
)) {
1071 tevent_req_nterror(req
, status
);
1076 status
= smb_bytes_talloc_string(cli
,
1082 if (!NT_STATUS_IS_OK(status
)) {
1083 tevent_req_nterror(req
, status
);
1088 status
= smb_bytes_talloc_string(cli
,
1090 &cli
->server_domain
,
1094 if (!NT_STATUS_IS_OK(status
)) {
1095 tevent_req_nterror(req
, status
);
1100 if (strstr(cli
->server_type
, "Samba")) {
1101 cli
->is_samba
= True
;
1104 status
= cli_set_username(cli
, state
->user
);
1105 if (tevent_req_nterror(req
, status
)) {
1108 if (cli_simple_set_signing(cli
, state
->session_key
, state
->response
)
1109 && !cli_check_sign_mac(cli
, (char *)in
, 1)) {
1110 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1113 if (state
->session_key
.data
) {
1114 /* Have plaintext orginal */
1115 cli_set_session_key(cli
, state
->session_key
);
1117 tevent_req_done(req
);
1120 static NTSTATUS
cli_session_setup_nt1_recv(struct tevent_req
*req
)
1122 return tevent_req_simple_recv_ntstatus(req
);
1125 static NTSTATUS
cli_session_setup_nt1(struct cli_state
*cli
, const char *user
,
1126 const char *pass
, size_t passlen
,
1127 const char *ntpass
, size_t ntpasslen
,
1128 const char *workgroup
)
1130 TALLOC_CTX
*frame
= talloc_stackframe();
1131 struct event_context
*ev
;
1132 struct tevent_req
*req
;
1133 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1135 if (cli_has_async_calls(cli
)) {
1137 * Can't use sync call while an async call is in flight
1139 status
= NT_STATUS_INVALID_PARAMETER
;
1142 ev
= event_context_init(frame
);
1146 req
= cli_session_setup_nt1_send(frame
, ev
, cli
, user
, pass
, passlen
,
1147 ntpass
, ntpasslen
, workgroup
);
1151 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1154 status
= cli_session_setup_nt1_recv(req
);
1157 if (!NT_STATUS_IS_OK(status
)) {
1158 cli_set_error(cli
, status
);
1163 /* The following is calculated from :
1165 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
1166 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1170 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1172 struct cli_sesssetup_blob_state
{
1173 struct tevent_context
*ev
;
1174 struct cli_state
*cli
;
1176 uint16_t max_blob_size
;
1185 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state
*state
,
1186 struct tevent_req
**psubreq
);
1187 static void cli_sesssetup_blob_done(struct tevent_req
*subreq
);
1189 static struct tevent_req
*cli_sesssetup_blob_send(TALLOC_CTX
*mem_ctx
,
1190 struct tevent_context
*ev
,
1191 struct cli_state
*cli
,
1194 struct tevent_req
*req
, *subreq
;
1195 struct cli_sesssetup_blob_state
*state
;
1197 req
= tevent_req_create(mem_ctx
, &state
,
1198 struct cli_sesssetup_blob_state
);
1206 if (cli
->max_xmit
< BASE_SESSSETUP_BLOB_PACKET_SIZE
+ 1) {
1207 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1208 "(was %u, need minimum %u)\n",
1209 (unsigned int)cli
->max_xmit
,
1210 BASE_SESSSETUP_BLOB_PACKET_SIZE
));
1211 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1212 return tevent_req_post(req
, ev
);
1214 state
->max_blob_size
=
1215 MIN(cli
->max_xmit
- BASE_SESSSETUP_BLOB_PACKET_SIZE
, 0xFFFF);
1217 if (!cli_sesssetup_blob_next(state
, &subreq
)) {
1218 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
1219 return tevent_req_post(req
, ev
);
1221 tevent_req_set_callback(subreq
, cli_sesssetup_blob_done
, req
);
1225 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state
*state
,
1226 struct tevent_req
**psubreq
)
1228 struct tevent_req
*subreq
;
1231 SCVAL(state
->vwv
+0, 0, 0xFF);
1232 SCVAL(state
->vwv
+0, 1, 0);
1233 SSVAL(state
->vwv
+1, 0, 0);
1234 SSVAL(state
->vwv
+2, 0, CLI_BUFFER_SIZE
);
1235 SSVAL(state
->vwv
+3, 0, 2);
1236 SSVAL(state
->vwv
+4, 0, 1);
1237 SIVAL(state
->vwv
+5, 0, 0);
1239 thistime
= MIN(state
->blob
.length
, state
->max_blob_size
);
1240 SSVAL(state
->vwv
+7, 0, thistime
);
1242 SSVAL(state
->vwv
+8, 0, 0);
1243 SSVAL(state
->vwv
+9, 0, 0);
1244 SIVAL(state
->vwv
+10, 0,
1245 cli_session_setup_capabilities(state
->cli
)
1246 | CAP_EXTENDED_SECURITY
);
1248 state
->buf
= (uint8_t *)talloc_memdup(state
, state
->blob
.data
,
1250 if (state
->buf
== NULL
) {
1253 state
->blob
.data
+= thistime
;
1254 state
->blob
.length
-= thistime
;
1256 state
->buf
= smb_bytes_push_str(state
->buf
, cli_ucs2(state
->cli
),
1258 state
->buf
= smb_bytes_push_str(state
->buf
, cli_ucs2(state
->cli
),
1260 if (state
->buf
== NULL
) {
1263 subreq
= cli_smb_send(state
, state
->ev
, state
->cli
, SMBsesssetupX
, 0,
1265 talloc_get_size(state
->buf
), state
->buf
);
1266 if (subreq
== NULL
) {
1273 static void cli_sesssetup_blob_done(struct tevent_req
*subreq
)
1275 struct tevent_req
*req
= tevent_req_callback_data(
1276 subreq
, struct tevent_req
);
1277 struct cli_sesssetup_blob_state
*state
= tevent_req_data(
1278 req
, struct cli_sesssetup_blob_state
);
1279 struct cli_state
*cli
= state
->cli
;
1286 uint16_t blob_length
;
1290 status
= cli_smb_recv(subreq
, state
, &inbuf
, 1, &wct
, &vwv
,
1291 &num_bytes
, &bytes
);
1292 TALLOC_FREE(subreq
);
1293 if (!NT_STATUS_IS_OK(status
)
1294 && !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1295 tevent_req_nterror(req
, status
);
1299 state
->status
= status
;
1300 TALLOC_FREE(state
->buf
);
1302 state
->inbuf
= (char *)inbuf
;
1303 cli
->vuid
= SVAL(state
->inbuf
, smb_uid
);
1305 blob_length
= SVAL(vwv
+3, 0);
1306 if (blob_length
> num_bytes
) {
1307 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
1310 state
->ret_blob
= data_blob_const(bytes
, blob_length
);
1312 p
= bytes
+ blob_length
;
1314 status
= smb_bytes_talloc_string(cli
,
1321 if (!NT_STATUS_IS_OK(status
)) {
1322 tevent_req_nterror(req
, status
);
1327 status
= smb_bytes_talloc_string(cli
,
1334 if (!NT_STATUS_IS_OK(status
)) {
1335 tevent_req_nterror(req
, status
);
1340 status
= smb_bytes_talloc_string(cli
,
1342 &cli
->server_domain
,
1347 if (!NT_STATUS_IS_OK(status
)) {
1348 tevent_req_nterror(req
, status
);
1353 if (strstr(cli
->server_type
, "Samba")) {
1354 cli
->is_samba
= True
;
1357 if (state
->blob
.length
!= 0) {
1361 if (!cli_sesssetup_blob_next(state
, &subreq
)) {
1362 tevent_req_nomem(NULL
, req
);
1365 tevent_req_set_callback(subreq
, cli_sesssetup_blob_done
, req
);
1368 tevent_req_done(req
);
1371 static NTSTATUS
cli_sesssetup_blob_recv(struct tevent_req
*req
,
1372 TALLOC_CTX
*mem_ctx
,
1376 struct cli_sesssetup_blob_state
*state
= tevent_req_data(
1377 req
, struct cli_sesssetup_blob_state
);
1381 if (tevent_req_is_nterror(req
, &status
)) {
1382 state
->cli
->vuid
= 0;
1386 inbuf
= talloc_move(mem_ctx
, &state
->inbuf
);
1387 if (pblob
!= NULL
) {
1388 *pblob
= state
->ret_blob
;
1390 if (pinbuf
!= NULL
) {
1393 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1394 return state
->status
;
1399 /****************************************************************************
1400 Use in-memory credentials cache
1401 ****************************************************************************/
1403 static void use_in_memory_ccache(void) {
1404 setenv(KRB5_ENV_CCNAME
, "MEMORY:cliconnect", 1);
1407 /****************************************************************************
1408 Do a spnego/kerberos encrypted session setup.
1409 ****************************************************************************/
1411 struct cli_session_setup_kerberos_state
{
1412 struct cli_state
*cli
;
1413 DATA_BLOB negTokenTarg
;
1414 DATA_BLOB session_key_krb5
;
1415 ADS_STATUS ads_status
;
1418 static void cli_session_setup_kerberos_done(struct tevent_req
*subreq
);
1420 static struct tevent_req
*cli_session_setup_kerberos_send(
1421 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
, struct cli_state
*cli
,
1422 const char *principal
, const char *workgroup
)
1424 struct tevent_req
*req
, *subreq
;
1425 struct cli_session_setup_kerberos_state
*state
;
1428 DEBUG(2,("Doing kerberos session setup\n"));
1430 req
= tevent_req_create(mem_ctx
, &state
,
1431 struct cli_session_setup_kerberos_state
);
1436 state
->ads_status
= ADS_SUCCESS
;
1438 cli_temp_set_signing(cli
);
1441 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1442 * we have to acquire a ticket. To be fixed later :-)
1444 rc
= spnego_gen_krb5_negTokenInit(state
, principal
, 0, &state
->negTokenTarg
,
1445 &state
->session_key_krb5
, 0, NULL
);
1447 DEBUG(1, ("cli_session_setup_kerberos: "
1448 "spnego_gen_krb5_negTokenInit failed: %s\n",
1449 error_message(rc
)));
1450 state
->ads_status
= ADS_ERROR_KRB5(rc
);
1451 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
1452 return tevent_req_post(req
, ev
);
1456 file_save("negTokenTarg.dat", state
->negTokenTarg
.data
,
1457 state
->negTokenTarg
.length
);
1460 subreq
= cli_sesssetup_blob_send(state
, ev
, cli
, state
->negTokenTarg
);
1461 if (tevent_req_nomem(subreq
, req
)) {
1462 return tevent_req_post(req
, ev
);
1464 tevent_req_set_callback(subreq
, cli_session_setup_kerberos_done
, req
);
1468 static void cli_session_setup_kerberos_done(struct tevent_req
*subreq
)
1470 struct tevent_req
*req
= tevent_req_callback_data(
1471 subreq
, struct tevent_req
);
1472 struct cli_session_setup_kerberos_state
*state
= tevent_req_data(
1473 req
, struct cli_session_setup_kerberos_state
);
1477 status
= cli_sesssetup_blob_recv(subreq
, talloc_tos(), NULL
, &inbuf
);
1478 if (!NT_STATUS_IS_OK(status
)) {
1479 TALLOC_FREE(subreq
);
1480 tevent_req_nterror(req
, status
);
1484 cli_set_session_key(state
->cli
, state
->session_key_krb5
);
1486 if (cli_simple_set_signing(state
->cli
, state
->session_key_krb5
,
1488 && !cli_check_sign_mac(state
->cli
, inbuf
, 1)) {
1489 TALLOC_FREE(subreq
);
1490 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1493 TALLOC_FREE(subreq
);
1494 tevent_req_done(req
);
1497 static ADS_STATUS
cli_session_setup_kerberos_recv(struct tevent_req
*req
)
1499 struct cli_session_setup_kerberos_state
*state
= tevent_req_data(
1500 req
, struct cli_session_setup_kerberos_state
);
1503 if (tevent_req_is_nterror(req
, &status
)) {
1504 return ADS_ERROR_NT(status
);
1506 return state
->ads_status
;
1509 static ADS_STATUS
cli_session_setup_kerberos(struct cli_state
*cli
,
1510 const char *principal
,
1511 const char *workgroup
)
1513 struct tevent_context
*ev
;
1514 struct tevent_req
*req
;
1515 ADS_STATUS status
= ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
1517 if (cli_has_async_calls(cli
)) {
1518 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
1520 ev
= tevent_context_init(talloc_tos());
1524 req
= cli_session_setup_kerberos_send(ev
, ev
, cli
, principal
,
1529 if (!tevent_req_poll(req
, ev
)) {
1530 status
= ADS_ERROR_SYSTEM(errno
);
1533 status
= cli_session_setup_kerberos_recv(req
);
1538 #endif /* HAVE_KRB5 */
1540 /****************************************************************************
1541 Do a spnego/NTLMSSP encrypted session setup.
1542 ****************************************************************************/
1544 struct cli_session_setup_ntlmssp_state
{
1545 struct tevent_context
*ev
;
1546 struct cli_state
*cli
;
1547 struct ntlmssp_state
*ntlmssp_state
;
1552 static int cli_session_setup_ntlmssp_state_destructor(
1553 struct cli_session_setup_ntlmssp_state
*state
)
1555 if (state
->ntlmssp_state
!= NULL
) {
1556 TALLOC_FREE(state
->ntlmssp_state
);
1561 static void cli_session_setup_ntlmssp_done(struct tevent_req
*req
);
1563 static struct tevent_req
*cli_session_setup_ntlmssp_send(
1564 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
, struct cli_state
*cli
,
1565 const char *user
, const char *pass
, const char *domain
)
1567 struct tevent_req
*req
, *subreq
;
1568 struct cli_session_setup_ntlmssp_state
*state
;
1571 const char *OIDs_ntlm
[] = {OID_NTLMSSP
, NULL
};
1573 req
= tevent_req_create(mem_ctx
, &state
,
1574 struct cli_session_setup_ntlmssp_state
);
1582 state
->ntlmssp_state
= NULL
;
1583 talloc_set_destructor(
1584 state
, cli_session_setup_ntlmssp_state_destructor
);
1586 cli_temp_set_signing(cli
);
1588 status
= ntlmssp_client_start(state
,
1591 lp_client_ntlmv2_auth(),
1592 &state
->ntlmssp_state
);
1593 if (!NT_STATUS_IS_OK(status
)) {
1596 ntlmssp_want_feature(state
->ntlmssp_state
,
1597 NTLMSSP_FEATURE_SESSION_KEY
);
1598 if (cli
->use_ccache
) {
1599 ntlmssp_want_feature(state
->ntlmssp_state
,
1600 NTLMSSP_FEATURE_CCACHE
);
1602 status
= ntlmssp_set_username(state
->ntlmssp_state
, user
);
1603 if (!NT_STATUS_IS_OK(status
)) {
1606 status
= ntlmssp_set_domain(state
->ntlmssp_state
, domain
);
1607 if (!NT_STATUS_IS_OK(status
)) {
1610 status
= ntlmssp_set_password(state
->ntlmssp_state
, pass
);
1611 if (!NT_STATUS_IS_OK(status
)) {
1614 status
= ntlmssp_update(state
->ntlmssp_state
, data_blob_null
,
1616 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1620 state
->blob_out
= spnego_gen_negTokenInit(state
, OIDs_ntlm
, &blob_out
, NULL
);
1621 data_blob_free(&blob_out
);
1623 subreq
= cli_sesssetup_blob_send(state
, ev
, cli
, state
->blob_out
);
1624 if (tevent_req_nomem(subreq
, req
)) {
1625 return tevent_req_post(req
, ev
);
1627 tevent_req_set_callback(subreq
, cli_session_setup_ntlmssp_done
, req
);
1630 tevent_req_nterror(req
, status
);
1631 return tevent_req_post(req
, ev
);
1634 static void cli_session_setup_ntlmssp_done(struct tevent_req
*subreq
)
1636 struct tevent_req
*req
= tevent_req_callback_data(
1637 subreq
, struct tevent_req
);
1638 struct cli_session_setup_ntlmssp_state
*state
= tevent_req_data(
1639 req
, struct cli_session_setup_ntlmssp_state
);
1640 DATA_BLOB blob_in
, msg_in
, blob_out
;
1645 status
= cli_sesssetup_blob_recv(subreq
, talloc_tos(), &blob_in
,
1647 TALLOC_FREE(subreq
);
1648 data_blob_free(&state
->blob_out
);
1650 if (NT_STATUS_IS_OK(status
)) {
1651 if (state
->cli
->server_domain
[0] == '\0') {
1652 TALLOC_FREE(state
->cli
->server_domain
);
1653 state
->cli
->server_domain
= talloc_strdup(state
->cli
,
1654 state
->ntlmssp_state
->server
.netbios_domain
);
1655 if (state
->cli
->server_domain
== NULL
) {
1656 TALLOC_FREE(subreq
);
1657 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
1661 cli_set_session_key(
1662 state
->cli
, state
->ntlmssp_state
->session_key
);
1664 if (cli_simple_set_signing(
1665 state
->cli
, state
->ntlmssp_state
->session_key
,
1667 && !cli_check_sign_mac(state
->cli
, inbuf
, 1)) {
1668 TALLOC_FREE(subreq
);
1669 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1672 TALLOC_FREE(subreq
);
1673 TALLOC_FREE(state
->ntlmssp_state
);
1674 tevent_req_done(req
);
1677 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1678 tevent_req_nterror(req
, status
);
1682 if (blob_in
.length
== 0) {
1683 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
1687 if ((state
->turn
== 1)
1688 && NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1689 DATA_BLOB tmp_blob
= data_blob_null
;
1690 /* the server might give us back two challenges */
1691 parse_ret
= spnego_parse_challenge(state
, blob_in
, &msg_in
,
1693 data_blob_free(&tmp_blob
);
1695 parse_ret
= spnego_parse_auth_response(state
, blob_in
, status
,
1696 OID_NTLMSSP
, &msg_in
);
1701 DEBUG(3,("Failed to parse auth response\n"));
1702 if (NT_STATUS_IS_OK(status
)
1703 || NT_STATUS_EQUAL(status
,
1704 NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1706 req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
1711 status
= ntlmssp_update(state
->ntlmssp_state
, msg_in
, &blob_out
);
1713 if (!NT_STATUS_IS_OK(status
)
1714 && !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1715 TALLOC_FREE(subreq
);
1716 TALLOC_FREE(state
->ntlmssp_state
);
1717 tevent_req_nterror(req
, status
);
1721 state
->blob_out
= spnego_gen_auth(state
, blob_out
);
1722 TALLOC_FREE(subreq
);
1723 if (tevent_req_nomem(state
->blob_out
.data
, req
)) {
1727 subreq
= cli_sesssetup_blob_send(state
, state
->ev
, state
->cli
,
1729 if (tevent_req_nomem(subreq
, req
)) {
1732 tevent_req_set_callback(subreq
, cli_session_setup_ntlmssp_done
, req
);
1735 static NTSTATUS
cli_session_setup_ntlmssp_recv(struct tevent_req
*req
)
1737 struct cli_session_setup_ntlmssp_state
*state
= tevent_req_data(
1738 req
, struct cli_session_setup_ntlmssp_state
);
1741 if (tevent_req_is_nterror(req
, &status
)) {
1742 state
->cli
->vuid
= 0;
1745 return NT_STATUS_OK
;
1748 static NTSTATUS
cli_session_setup_ntlmssp(struct cli_state
*cli
,
1753 struct tevent_context
*ev
;
1754 struct tevent_req
*req
;
1755 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1757 if (cli_has_async_calls(cli
)) {
1758 return NT_STATUS_INVALID_PARAMETER
;
1760 ev
= tevent_context_init(talloc_tos());
1764 req
= cli_session_setup_ntlmssp_send(ev
, ev
, cli
, user
, pass
, domain
);
1768 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1771 status
= cli_session_setup_ntlmssp_recv(req
);
1774 if (!NT_STATUS_IS_OK(status
)) {
1775 cli_set_error(cli
, status
);
1780 /****************************************************************************
1781 Do a spnego encrypted session setup.
1783 user_domain: The shortname of the domain the user/machine is a member of.
1784 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1785 ****************************************************************************/
1787 ADS_STATUS
cli_session_setup_spnego(struct cli_state
*cli
, const char *user
,
1788 const char *pass
, const char *user_domain
,
1789 const char * dest_realm
)
1791 char *principal
= NULL
;
1792 char *OIDs
[ASN1_MAX_OIDS
];
1795 const char *p
= NULL
;
1796 char *account
= NULL
;
1799 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli
->secblob
.length
));
1801 /* the server might not even do spnego */
1802 if (cli
->secblob
.length
<= 16) {
1803 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1808 file_save("negprot.dat", cli
->secblob
.data
, cli
->secblob
.length
);
1811 /* there is 16 bytes of GUID before the real spnego packet starts */
1812 blob
= data_blob(cli
->secblob
.data
+16, cli
->secblob
.length
-16);
1814 /* The server sent us the first part of the SPNEGO exchange in the
1815 * negprot reply. It is WRONG to depend on the principal sent in the
1816 * negprot reply, but right now we do it. If we don't receive one,
1817 * we try to best guess, then fall back to NTLM. */
1818 if (!spnego_parse_negTokenInit(talloc_tos(), blob
, OIDs
, &principal
, NULL
) ||
1820 data_blob_free(&blob
);
1821 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
1823 data_blob_free(&blob
);
1825 /* make sure the server understands kerberos */
1826 for (i
=0;OIDs
[i
];i
++) {
1828 DEBUG(3,("got OID=%s\n", OIDs
[i
]));
1830 DEBUGADD(3,("got OID=%s\n", OIDs
[i
]));
1831 if (strcmp(OIDs
[i
], OID_KERBEROS5_OLD
) == 0 ||
1832 strcmp(OIDs
[i
], OID_KERBEROS5
) == 0) {
1833 cli
->got_kerberos_mechanism
= True
;
1835 talloc_free(OIDs
[i
]);
1838 DEBUG(3,("got principal=%s\n", principal
? principal
: "<null>"));
1840 status
= cli_set_username(cli
, user
);
1841 if (!NT_STATUS_IS_OK(status
)) {
1842 TALLOC_FREE(principal
);
1843 return ADS_ERROR_NT(status
);
1847 /* If password is set we reauthenticate to kerberos server
1848 * and do not store results */
1850 if (cli
->got_kerberos_mechanism
&& cli
->use_kerberos
) {
1853 if (pass
&& *pass
) {
1856 use_in_memory_ccache();
1857 ret
= kerberos_kinit_password(user
, pass
, 0 /* no time correction for now */, NULL
);
1860 TALLOC_FREE(principal
);
1861 DEBUG(0, ("Kinit failed: %s\n", error_message(ret
)));
1862 if (cli
->fallback_after_kerberos
)
1864 return ADS_ERROR_KRB5(ret
);
1868 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1870 if (!lp_client_use_spnego_principal() || strequal(principal
, ADS_IGNORE_PRINCIPAL
)) {
1871 TALLOC_FREE(principal
);
1874 if (principal
== NULL
&&
1875 !is_ipaddress(cli
->desthost
) &&
1876 !strequal(STAR_SMBSERVER
,
1880 DEBUG(3,("cli_session_setup_spnego: using target "
1881 "hostname not SPNEGO principal\n"));
1883 host
= strchr_m(cli
->desthost
, '.');
1885 realm
= SMB_STRDUP(dest_realm
);
1890 realm
= kerberos_get_realm_from_hostname(cli
->desthost
);
1892 /* NetBIOS name - use our realm. */
1893 realm
= kerberos_get_default_realm_from_ccache();
1897 if (realm
&& *realm
) {
1898 principal
= talloc_asprintf(talloc_tos(),
1904 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
1906 DEBUG(3,("cli_session_setup_spnego: guessed "
1907 "server principal=%s\n",
1908 principal
? principal
: "<null>"));
1914 rc
= cli_session_setup_kerberos(cli
, principal
,
1916 if (ADS_ERR_OK(rc
) || !cli
->fallback_after_kerberos
) {
1917 TALLOC_FREE(principal
);
1924 TALLOC_FREE(principal
);
1928 account
= talloc_strdup(talloc_tos(), user
);
1930 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
1933 /* when falling back to ntlmssp while authenticating with a machine
1934 * account strip off the realm - gd */
1936 if ((p
= strchr_m(user
, '@')) != NULL
) {
1937 account
[PTR_DIFF(p
,user
)] = '\0';
1940 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli
, account
, pass
, user_domain
));
1943 /****************************************************************************
1944 Send a session setup. The username and workgroup is in UNIX character
1945 format and must be converted to DOS codepage format before sending. If the
1946 password is in plaintext, the same should be done.
1947 ****************************************************************************/
1949 NTSTATUS
cli_session_setup(struct cli_state
*cli
,
1951 const char *pass
, int passlen
,
1952 const char *ntpass
, int ntpasslen
,
1953 const char *workgroup
)
1959 user2
= talloc_strdup(talloc_tos(), user
);
1961 user2
= talloc_strdup(talloc_tos(), "");
1963 if (user2
== NULL
) {
1964 return NT_STATUS_NO_MEMORY
;
1971 /* allow for workgroups as part of the username */
1972 if ((p
=strchr_m(user2
,'\\')) || (p
=strchr_m(user2
,'/')) ||
1973 (p
=strchr_m(user2
,*lp_winbind_separator()))) {
1979 if (cli
->protocol
< PROTOCOL_LANMAN1
) {
1980 return NT_STATUS_OK
;
1983 /* now work out what sort of session setup we are going to
1984 do. I have split this into separate functions to make the
1985 flow a bit easier to understand (tridge) */
1987 /* if its an older server then we have to use the older request format */
1989 if (cli
->protocol
< PROTOCOL_NT1
) {
1990 if (!lp_client_lanman_auth() && passlen
!= 24 && (*pass
)) {
1991 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
1992 " or 'client ntlmv2 auth = yes'\n"));
1993 return NT_STATUS_ACCESS_DENIED
;
1996 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) == 0 &&
1997 !lp_client_plaintext_auth() && (*pass
)) {
1998 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
1999 " or 'client ntlmv2 auth = yes'\n"));
2000 return NT_STATUS_ACCESS_DENIED
;
2003 return cli_session_setup_lanman2(cli
, user
, pass
, passlen
,
2007 /* if no user is supplied then we have to do an anonymous connection.
2008 passwords are ignored */
2010 if (!user
|| !*user
)
2011 return cli_session_setup_guest(cli
);
2013 /* if the server is share level then send a plaintext null
2014 password at this point. The password is sent in the tree
2017 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
) == 0)
2018 return cli_session_setup_plain(cli
, user
, "", workgroup
);
2020 /* if the server doesn't support encryption then we have to use
2021 plaintext. The second password is ignored */
2023 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) == 0) {
2024 if (!lp_client_plaintext_auth() && (*pass
)) {
2025 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2026 " or 'client ntlmv2 auth = yes'\n"));
2027 return NT_STATUS_ACCESS_DENIED
;
2029 return cli_session_setup_plain(cli
, user
, pass
, workgroup
);
2032 /* if the server supports extended security then use SPNEGO */
2034 if (cli
->capabilities
& CAP_EXTENDED_SECURITY
) {
2035 ADS_STATUS status
= cli_session_setup_spnego(cli
, user
, pass
,
2037 if (!ADS_ERR_OK(status
)) {
2038 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status
)));
2039 return ads_ntstatus(status
);
2044 /* otherwise do a NT1 style session setup */
2045 status
= cli_session_setup_nt1(cli
, user
, pass
, passlen
,
2046 ntpass
, ntpasslen
, workgroup
);
2047 if (!NT_STATUS_IS_OK(status
)) {
2048 DEBUG(3,("cli_session_setup: NT1 session setup "
2049 "failed: %s\n", nt_errstr(status
)));
2054 if (strstr(cli
->server_type
, "Samba")) {
2055 cli
->is_samba
= True
;
2058 return NT_STATUS_OK
;
2061 /****************************************************************************
2063 *****************************************************************************/
2065 struct cli_ulogoff_state
{
2066 struct cli_state
*cli
;
2070 static void cli_ulogoff_done(struct tevent_req
*subreq
);
2072 struct tevent_req
*cli_ulogoff_send(TALLOC_CTX
*mem_ctx
,
2073 struct tevent_context
*ev
,
2074 struct cli_state
*cli
)
2076 struct tevent_req
*req
, *subreq
;
2077 struct cli_ulogoff_state
*state
;
2079 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ulogoff_state
);
2085 SCVAL(state
->vwv
+0, 0, 0xFF);
2086 SCVAL(state
->vwv
+1, 0, 0);
2087 SSVAL(state
->vwv
+2, 0, 0);
2089 subreq
= cli_smb_send(state
, ev
, cli
, SMBulogoffX
, 0, 2, state
->vwv
,
2091 if (tevent_req_nomem(subreq
, req
)) {
2092 return tevent_req_post(req
, ev
);
2094 tevent_req_set_callback(subreq
, cli_ulogoff_done
, req
);
2098 static void cli_ulogoff_done(struct tevent_req
*subreq
)
2100 struct tevent_req
*req
= tevent_req_callback_data(
2101 subreq
, struct tevent_req
);
2102 struct cli_ulogoff_state
*state
= tevent_req_data(
2103 req
, struct cli_ulogoff_state
);
2106 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2107 if (!NT_STATUS_IS_OK(status
)) {
2108 tevent_req_nterror(req
, status
);
2111 state
->cli
->vuid
= -1;
2112 tevent_req_done(req
);
2115 NTSTATUS
cli_ulogoff_recv(struct tevent_req
*req
)
2117 return tevent_req_simple_recv_ntstatus(req
);
2120 NTSTATUS
cli_ulogoff(struct cli_state
*cli
)
2122 struct tevent_context
*ev
;
2123 struct tevent_req
*req
;
2124 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2126 if (cli_has_async_calls(cli
)) {
2127 return NT_STATUS_INVALID_PARAMETER
;
2129 ev
= tevent_context_init(talloc_tos());
2133 req
= cli_ulogoff_send(ev
, ev
, cli
);
2137 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2140 status
= cli_ulogoff_recv(req
);
2143 if (!NT_STATUS_IS_OK(status
)) {
2144 cli_set_error(cli
, status
);
2149 /****************************************************************************
2151 ****************************************************************************/
2153 struct cli_tcon_andx_state
{
2154 struct cli_state
*cli
;
2159 static void cli_tcon_andx_done(struct tevent_req
*subreq
);
2161 struct tevent_req
*cli_tcon_andx_create(TALLOC_CTX
*mem_ctx
,
2162 struct event_context
*ev
,
2163 struct cli_state
*cli
,
2164 const char *share
, const char *dev
,
2165 const char *pass
, int passlen
,
2166 struct tevent_req
**psmbreq
)
2168 struct tevent_req
*req
, *subreq
;
2169 struct cli_tcon_andx_state
*state
;
2177 req
= tevent_req_create(mem_ctx
, &state
, struct cli_tcon_andx_state
);
2184 cli
->share
= talloc_strdup(cli
, share
);
2189 /* in user level security don't send a password now */
2190 if (cli
->sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
) {
2193 } else if (pass
== NULL
) {
2194 DEBUG(1, ("Server not using user level security and no "
2195 "password supplied.\n"));
2199 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) &&
2200 *pass
&& passlen
!= 24) {
2201 if (!lp_client_lanman_auth()) {
2202 DEBUG(1, ("Server requested LANMAN password "
2203 "(share-level security) but "
2204 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2209 * Non-encrypted passwords - convert to DOS codepage before
2213 SMBencrypt(pass
, cli
->secblob
.data
, (uchar
*)pword
);
2215 if((cli
->sec_mode
& (NEGOTIATE_SECURITY_USER_LEVEL
2216 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
))
2218 if (!lp_client_plaintext_auth() && (*pass
)) {
2219 DEBUG(1, ("Server requested plaintext "
2221 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2226 * Non-encrypted passwords - convert to DOS codepage
2229 passlen
= clistr_push(cli
, pword
, pass
, sizeof(pword
),
2231 if (passlen
== -1) {
2232 DEBUG(1, ("clistr_push(pword) failed\n"));
2237 memcpy(pword
, pass
, passlen
);
2242 SCVAL(vwv
+0, 0, 0xFF);
2245 SSVAL(vwv
+2, 0, TCONX_FLAG_EXTENDED_RESPONSE
);
2246 SSVAL(vwv
+3, 0, passlen
);
2249 bytes
= (uint8_t *)talloc_memdup(state
, pword
, passlen
);
2251 bytes
= talloc_array(state
, uint8_t, 0);
2257 tmp
= talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2258 cli
->desthost
, share
);
2263 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), tmp
, strlen(tmp
)+1,
2268 * Add the devicetype
2270 tmp
= talloc_strdup_upper(talloc_tos(), dev
);
2275 bytes
= smb_bytes_push_str(bytes
, false, tmp
, strlen(tmp
)+1, NULL
);
2278 if (bytes
== NULL
) {
2283 state
->bytes
.iov_base
= (void *)bytes
;
2284 state
->bytes
.iov_len
= talloc_get_size(bytes
);
2286 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBtconX
, 0, 4, vwv
,
2288 if (subreq
== NULL
) {
2292 tevent_req_set_callback(subreq
, cli_tcon_andx_done
, req
);
2297 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2298 return tevent_req_post(req
, ev
);
2301 struct tevent_req
*cli_tcon_andx_send(TALLOC_CTX
*mem_ctx
,
2302 struct event_context
*ev
,
2303 struct cli_state
*cli
,
2304 const char *share
, const char *dev
,
2305 const char *pass
, int passlen
)
2307 struct tevent_req
*req
, *subreq
;
2310 req
= cli_tcon_andx_create(mem_ctx
, ev
, cli
, share
, dev
, pass
, passlen
,
2315 if (subreq
== NULL
) {
2318 status
= cli_smb_req_send(subreq
);
2319 if (!NT_STATUS_IS_OK(status
)) {
2320 tevent_req_nterror(req
, status
);
2321 return tevent_req_post(req
, ev
);
2326 static void cli_tcon_andx_done(struct tevent_req
*subreq
)
2328 struct tevent_req
*req
= tevent_req_callback_data(
2329 subreq
, struct tevent_req
);
2330 struct cli_tcon_andx_state
*state
= tevent_req_data(
2331 req
, struct cli_tcon_andx_state
);
2332 struct cli_state
*cli
= state
->cli
;
2341 status
= cli_smb_recv(subreq
, state
, &in
, 0, &wct
, &vwv
,
2342 &num_bytes
, &bytes
);
2343 TALLOC_FREE(subreq
);
2344 if (!NT_STATUS_IS_OK(status
)) {
2345 tevent_req_nterror(req
, status
);
2352 if (clistr_pull_talloc(cli
,
2354 SVAL(inbuf
, smb_flg2
),
2358 STR_TERMINATE
|STR_ASCII
) == -1) {
2359 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
2363 cli
->dev
= talloc_strdup(cli
, "");
2364 if (cli
->dev
== NULL
) {
2365 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
2370 if ((cli
->protocol
>= PROTOCOL_NT1
) && (num_bytes
== 3)) {
2371 /* almost certainly win95 - enable bug fixes */
2376 * Make sure that we have the optional support 16-bit field. WCT > 2.
2377 * Avoids issues when connecting to Win9x boxes sharing files
2380 cli
->dfsroot
= false;
2382 if ((wct
> 2) && (cli
->protocol
>= PROTOCOL_LANMAN2
)) {
2383 cli
->dfsroot
= ((SVAL(vwv
+2, 0) & SMB_SHARE_IN_DFS
) != 0);
2386 cli
->cnum
= SVAL(inbuf
,smb_tid
);
2387 tevent_req_done(req
);
2390 NTSTATUS
cli_tcon_andx_recv(struct tevent_req
*req
)
2392 return tevent_req_simple_recv_ntstatus(req
);
2395 NTSTATUS
cli_tcon_andx(struct cli_state
*cli
, const char *share
,
2396 const char *dev
, const char *pass
, int passlen
)
2398 TALLOC_CTX
*frame
= talloc_stackframe();
2399 struct event_context
*ev
;
2400 struct tevent_req
*req
;
2401 NTSTATUS status
= NT_STATUS_OK
;
2403 if (cli_has_async_calls(cli
)) {
2405 * Can't use sync call while an async call is in flight
2407 status
= NT_STATUS_INVALID_PARAMETER
;
2411 ev
= event_context_init(frame
);
2413 status
= NT_STATUS_NO_MEMORY
;
2417 req
= cli_tcon_andx_send(frame
, ev
, cli
, share
, dev
, pass
, passlen
);
2419 status
= NT_STATUS_NO_MEMORY
;
2423 if (!tevent_req_poll(req
, ev
)) {
2424 status
= map_nt_error_from_unix(errno
);
2428 status
= cli_tcon_andx_recv(req
);
2431 if (!NT_STATUS_IS_OK(status
)) {
2432 cli_set_error(cli
, status
);
2437 /****************************************************************************
2438 Send a tree disconnect.
2439 ****************************************************************************/
2441 struct cli_tdis_state
{
2442 struct cli_state
*cli
;
2445 static void cli_tdis_done(struct tevent_req
*subreq
);
2447 struct tevent_req
*cli_tdis_send(TALLOC_CTX
*mem_ctx
,
2448 struct tevent_context
*ev
,
2449 struct cli_state
*cli
)
2451 struct tevent_req
*req
, *subreq
;
2452 struct cli_tdis_state
*state
;
2454 req
= tevent_req_create(mem_ctx
, &state
, struct cli_tdis_state
);
2460 subreq
= cli_smb_send(state
, ev
, cli
, SMBtdis
, 0, 0, NULL
, 0, NULL
);
2461 if (tevent_req_nomem(subreq
, req
)) {
2462 return tevent_req_post(req
, ev
);
2464 tevent_req_set_callback(subreq
, cli_tdis_done
, req
);
2468 static void cli_tdis_done(struct tevent_req
*subreq
)
2470 struct tevent_req
*req
= tevent_req_callback_data(
2471 subreq
, struct tevent_req
);
2472 struct cli_tdis_state
*state
= tevent_req_data(
2473 req
, struct cli_tdis_state
);
2476 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2477 TALLOC_FREE(subreq
);
2478 if (!NT_STATUS_IS_OK(status
)) {
2479 tevent_req_nterror(req
, status
);
2482 state
->cli
->cnum
= -1;
2483 tevent_req_done(req
);
2486 NTSTATUS
cli_tdis_recv(struct tevent_req
*req
)
2488 return tevent_req_simple_recv_ntstatus(req
);
2491 NTSTATUS
cli_tdis(struct cli_state
*cli
)
2493 struct tevent_context
*ev
;
2494 struct tevent_req
*req
;
2495 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2497 if (cli_has_async_calls(cli
)) {
2498 return NT_STATUS_INVALID_PARAMETER
;
2500 ev
= tevent_context_init(talloc_tos());
2504 req
= cli_tdis_send(ev
, ev
, cli
);
2508 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2511 status
= cli_tdis_recv(req
);
2514 if (!NT_STATUS_IS_OK(status
)) {
2515 cli_set_error(cli
, status
);
2520 /****************************************************************************
2521 Send a negprot command.
2522 ****************************************************************************/
2524 struct cli_negprot_state
{
2525 struct cli_state
*cli
;
2528 static void cli_negprot_done(struct tevent_req
*subreq
);
2530 struct tevent_req
*cli_negprot_send(TALLOC_CTX
*mem_ctx
,
2531 struct event_context
*ev
,
2532 struct cli_state
*cli
)
2534 struct tevent_req
*req
, *subreq
;
2535 struct cli_negprot_state
*state
;
2536 uint8_t *bytes
= NULL
;
2540 req
= tevent_req_create(mem_ctx
, &state
, struct cli_negprot_state
);
2546 if (cli
->protocol
< PROTOCOL_NT1
)
2547 cli
->use_spnego
= False
;
2549 /* setup the protocol strings */
2550 for (numprots
=0; numprots
< ARRAY_SIZE(prots
); numprots
++) {
2552 if (prots
[numprots
].prot
> cli
->protocol
) {
2555 bytes
= (uint8_t *)talloc_append_blob(
2556 state
, bytes
, data_blob_const(&c
, sizeof(c
)));
2557 if (tevent_req_nomem(bytes
, req
)) {
2558 return tevent_req_post(req
, ev
);
2560 bytes
= smb_bytes_push_str(bytes
, false,
2561 prots
[numprots
].name
,
2562 strlen(prots
[numprots
].name
)+1,
2564 if (tevent_req_nomem(bytes
, req
)) {
2565 return tevent_req_post(req
, ev
);
2572 subreq
= cli_smb_send(state
, ev
, cli
, SMBnegprot
, 0, 0, NULL
,
2573 talloc_get_size(bytes
), bytes
);
2576 if (tevent_req_nomem(subreq
, req
)) {
2577 return tevent_req_post(req
, ev
);
2579 tevent_req_set_callback(subreq
, cli_negprot_done
, req
);
2583 static void cli_negprot_done(struct tevent_req
*subreq
)
2585 struct tevent_req
*req
= tevent_req_callback_data(
2586 subreq
, struct tevent_req
);
2587 struct cli_negprot_state
*state
= tevent_req_data(
2588 req
, struct cli_negprot_state
);
2589 struct cli_state
*cli
= state
->cli
;
2598 status
= cli_smb_recv(subreq
, state
, &inbuf
, 1, &wct
, &vwv
,
2599 &num_bytes
, &bytes
);
2600 TALLOC_FREE(subreq
);
2601 if (!NT_STATUS_IS_OK(status
)) {
2602 tevent_req_nterror(req
, status
);
2606 protnum
= SVAL(vwv
, 0);
2608 if ((protnum
>= ARRAY_SIZE(prots
))
2609 || (prots
[protnum
].prot
> cli
->protocol
)) {
2610 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
2614 cli
->protocol
= prots
[protnum
].prot
;
2616 if ((cli
->protocol
< PROTOCOL_NT1
) &&
2617 client_is_signing_mandatory(cli
)) {
2618 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2619 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2623 if (cli
->protocol
>= PROTOCOL_NT1
) {
2625 bool negotiated_smb_signing
= false;
2628 cli
->sec_mode
= CVAL(vwv
+ 1, 0);
2629 cli
->max_mux
= SVAL(vwv
+ 1, 1);
2630 cli
->max_xmit
= IVAL(vwv
+ 3, 1);
2631 cli
->sesskey
= IVAL(vwv
+ 7, 1);
2632 cli
->serverzone
= SVALS(vwv
+ 15, 1);
2633 cli
->serverzone
*= 60;
2634 /* this time arrives in real GMT */
2635 ts
= interpret_long_date(((char *)(vwv
+11))+1);
2636 cli
->servertime
= ts
.tv_sec
;
2637 cli
->secblob
= data_blob(bytes
, num_bytes
);
2638 cli
->capabilities
= IVAL(vwv
+ 9, 1);
2639 if (cli
->capabilities
& CAP_RAW_MODE
) {
2640 cli
->readbraw_supported
= True
;
2641 cli
->writebraw_supported
= True
;
2643 /* work out if they sent us a workgroup */
2644 if (!(cli
->capabilities
& CAP_EXTENDED_SECURITY
) &&
2645 smb_buflen(cli
->inbuf
) > 8) {
2646 clistr_pull(cli
->inbuf
, cli
->server_domain
,
2647 bytes
+8, sizeof(cli
->server_domain
),
2649 STR_UNICODE
|STR_NOALIGN
);
2653 * As signing is slow we only turn it on if either the client or
2654 * the server require it. JRA.
2657 if (cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_REQUIRED
) {
2658 /* Fail if server says signing is mandatory and we don't want to support it. */
2659 if (!client_is_signing_allowed(cli
)) {
2660 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2661 tevent_req_nterror(req
,
2662 NT_STATUS_ACCESS_DENIED
);
2665 negotiated_smb_signing
= true;
2666 } else if (client_is_signing_mandatory(cli
) && client_is_signing_allowed(cli
)) {
2667 /* Fail if client says signing is mandatory and the server doesn't support it. */
2668 if (!(cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_ENABLED
)) {
2669 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2670 tevent_req_nterror(req
,
2671 NT_STATUS_ACCESS_DENIED
);
2674 negotiated_smb_signing
= true;
2675 } else if (cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_ENABLED
) {
2676 negotiated_smb_signing
= true;
2679 if (negotiated_smb_signing
) {
2680 cli_set_signing_negotiated(cli
);
2683 if (cli
->capabilities
& (CAP_LARGE_READX
|CAP_LARGE_WRITEX
)) {
2684 SAFE_FREE(cli
->outbuf
);
2685 SAFE_FREE(cli
->inbuf
);
2686 cli
->outbuf
= (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE
+LARGE_WRITEX_HDR_SIZE
+SAFETY_MARGIN
);
2687 cli
->inbuf
= (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE
+LARGE_WRITEX_HDR_SIZE
+SAFETY_MARGIN
);
2688 if (!cli
->outbuf
|| !cli
->inbuf
) {
2689 tevent_req_nterror(req
,
2690 NT_STATUS_NO_MEMORY
);
2693 cli
->bufsize
= CLI_SAMBA_MAX_LARGE_READX_SIZE
+ LARGE_WRITEX_HDR_SIZE
;
2696 } else if (cli
->protocol
>= PROTOCOL_LANMAN1
) {
2697 cli
->use_spnego
= False
;
2698 cli
->sec_mode
= SVAL(vwv
+ 1, 0);
2699 cli
->max_xmit
= SVAL(vwv
+ 2, 0);
2700 cli
->max_mux
= SVAL(vwv
+ 3, 0);
2701 cli
->sesskey
= IVAL(vwv
+ 6, 0);
2702 cli
->serverzone
= SVALS(vwv
+ 10, 0);
2703 cli
->serverzone
*= 60;
2704 /* this time is converted to GMT by make_unix_date */
2705 cli
->servertime
= make_unix_date(
2706 (char *)(vwv
+ 8), cli
->serverzone
);
2707 cli
->readbraw_supported
= ((SVAL(vwv
+ 5, 0) & 0x1) != 0);
2708 cli
->writebraw_supported
= ((SVAL(vwv
+ 5, 0) & 0x2) != 0);
2709 cli
->secblob
= data_blob(bytes
, num_bytes
);
2711 /* the old core protocol */
2712 cli
->use_spnego
= False
;
2714 cli
->serverzone
= get_time_zone(time(NULL
));
2717 cli
->max_xmit
= MIN(cli
->max_xmit
, CLI_BUFFER_SIZE
);
2719 /* a way to force ascii SMB */
2720 if (getenv("CLI_FORCE_ASCII"))
2721 cli
->capabilities
&= ~CAP_UNICODE
;
2723 tevent_req_done(req
);
2726 NTSTATUS
cli_negprot_recv(struct tevent_req
*req
)
2728 return tevent_req_simple_recv_ntstatus(req
);
2731 NTSTATUS
cli_negprot(struct cli_state
*cli
)
2733 TALLOC_CTX
*frame
= talloc_stackframe();
2734 struct event_context
*ev
;
2735 struct tevent_req
*req
;
2736 NTSTATUS status
= NT_STATUS_OK
;
2738 if (cli_has_async_calls(cli
)) {
2740 * Can't use sync call while an async call is in flight
2742 status
= NT_STATUS_INVALID_PARAMETER
;
2746 ev
= event_context_init(frame
);
2748 status
= NT_STATUS_NO_MEMORY
;
2752 req
= cli_negprot_send(frame
, ev
, cli
);
2754 status
= NT_STATUS_NO_MEMORY
;
2758 if (!tevent_req_poll(req
, ev
)) {
2759 status
= map_nt_error_from_unix(errno
);
2763 status
= cli_negprot_recv(req
);
2766 if (!NT_STATUS_IS_OK(status
)) {
2767 cli_set_error(cli
, status
);
2772 /****************************************************************************
2773 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
2774 ****************************************************************************/
2776 bool cli_session_request(struct cli_state
*cli
,
2777 struct nmb_name
*calling
, struct nmb_name
*called
)
2784 /* 445 doesn't have session request */
2785 if (cli
->port
== 445)
2788 memcpy(&(cli
->calling
), calling
, sizeof(*calling
));
2789 memcpy(&(cli
->called
), called
, sizeof(*called
));
2791 /* put in the destination name */
2793 tmp
= name_mangle(talloc_tos(), cli
->called
.name
,
2794 cli
->called
.name_type
);
2799 p
= cli
->outbuf
+len
;
2800 namelen
= name_len((unsigned char *)tmp
, talloc_get_size(tmp
));
2802 memcpy(p
, tmp
, namelen
);
2809 tmp
= name_mangle(talloc_tos(), cli
->calling
.name
,
2810 cli
->calling
.name_type
);
2815 p
= cli
->outbuf
+len
;
2816 namelen
= name_len((unsigned char *)tmp
, talloc_get_size(tmp
));
2818 memcpy(p
, tmp
, namelen
);
2823 /* send a session request (RFC 1002) */
2824 /* setup the packet length
2825 * Remove four bytes from the length count, since the length
2826 * field in the NBT Session Service header counts the number
2827 * of bytes which follow. The cli_send_smb() function knows
2828 * about this and accounts for those four bytes.
2832 _smb_setlen(cli
->outbuf
,len
);
2833 SCVAL(cli
->outbuf
,0,0x81);
2836 DEBUG(5,("Sent session request\n"));
2838 if (!cli_receive_smb(cli
))
2841 if (CVAL(cli
->inbuf
,0) == 0x84) {
2842 /* C. Hoch 9/14/95 Start */
2843 /* For information, here is the response structure.
2844 * We do the byte-twiddling to for portability.
2845 struct RetargetResponse{
2847 unsigned char flags;
2853 uint16_t port
= (CVAL(cli
->inbuf
,8)<<8)+CVAL(cli
->inbuf
,9);
2854 struct in_addr dest_ip
;
2857 /* SESSION RETARGET */
2858 putip((char *)&dest_ip
,cli
->inbuf
+4);
2859 in_addr_to_sockaddr_storage(&cli
->dest_ss
, dest_ip
);
2861 status
= open_socket_out(&cli
->dest_ss
, port
,
2862 LONG_CONNECT_TIMEOUT
, &cli
->fd
);
2863 if (!NT_STATUS_IS_OK(status
)) {
2867 DEBUG(3,("Retargeted\n"));
2869 set_socket_options(cli
->fd
, lp_socket_options());
2876 DEBUG(0,("Retarget recursion - failing\n"));
2880 ret
= cli_session_request(cli
, calling
, called
);
2884 } /* C. Hoch 9/14/95 End */
2886 if (CVAL(cli
->inbuf
,0) != 0x82) {
2887 /* This is the wrong place to put the error... JRA. */
2888 cli
->rap_error
= CVAL(cli
->inbuf
,4);
2898 static void smb_sock_connected(struct tevent_req
*req
)
2900 struct fd_struct
*pfd
= tevent_req_callback_data(
2901 req
, struct fd_struct
);
2905 status
= open_socket_out_defer_recv(req
, &fd
);
2906 if (NT_STATUS_IS_OK(status
)) {
2911 static NTSTATUS
open_smb_socket(const struct sockaddr_storage
*pss
,
2912 uint16_t *port
, int timeout
, int *pfd
)
2914 struct event_context
*ev
;
2915 struct tevent_req
*r139
, *r445
;
2916 struct fd_struct
*fd139
, *fd445
;
2917 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2920 return open_socket_out(pss
, *port
, timeout
, pfd
);
2923 ev
= event_context_init(talloc_tos());
2925 return NT_STATUS_NO_MEMORY
;
2928 fd139
= talloc(ev
, struct fd_struct
);
2929 if (fd139
== NULL
) {
2934 fd445
= talloc(ev
, struct fd_struct
);
2935 if (fd445
== NULL
) {
2940 r445
= open_socket_out_defer_send(ev
, ev
, timeval_set(0, 0),
2942 r139
= open_socket_out_defer_send(ev
, ev
, timeval_set(0, 3000),
2944 if ((r445
== NULL
) || (r139
== NULL
)) {
2947 tevent_req_set_callback(r445
, smb_sock_connected
, fd445
);
2948 tevent_req_set_callback(r139
, smb_sock_connected
, fd139
);
2950 while ((fd445
->fd
== -1) && (fd139
->fd
== -1)
2951 && (tevent_req_is_in_progress(r139
)
2952 || tevent_req_is_in_progress(r445
))) {
2953 event_loop_once(ev
);
2956 if ((fd139
->fd
!= -1) && (fd445
->fd
!= -1)) {
2961 if (fd445
->fd
!= -1) {
2964 status
= NT_STATUS_OK
;
2967 if (fd139
->fd
!= -1) {
2970 status
= NT_STATUS_OK
;
2974 status
= open_socket_out_defer_recv(r445
, &fd445
->fd
);
2980 /****************************************************************************
2981 Open the client sockets.
2982 ****************************************************************************/
2984 NTSTATUS
cli_connect(struct cli_state
*cli
,
2986 struct sockaddr_storage
*dest_ss
)
2989 int name_type
= 0x20;
2990 TALLOC_CTX
*frame
= talloc_stackframe();
2991 unsigned int num_addrs
= 0;
2993 struct sockaddr_storage
*ss_arr
= NULL
;
2996 /* reasonable default hostname */
2998 host
= STAR_SMBSERVER
;
3001 cli
->desthost
= talloc_strdup(cli
, host
);
3002 if (cli
->desthost
== NULL
) {
3003 return NT_STATUS_NO_MEMORY
;
3006 /* allow hostnames of the form NAME#xx and do a netbios lookup */
3007 if ((p
= strchr(cli
->desthost
, '#'))) {
3008 name_type
= strtol(p
+1, NULL
, 16);
3012 if (!dest_ss
|| is_zero_addr(dest_ss
)) {
3013 NTSTATUS status
=resolve_name_list(frame
,
3018 if (!NT_STATUS_IS_OK(status
)) {
3020 return NT_STATUS_BAD_NETWORK_NAME
;
3024 ss_arr
= TALLOC_P(frame
, struct sockaddr_storage
);
3027 return NT_STATUS_NO_MEMORY
;
3032 for (i
= 0; i
< num_addrs
; i
++) {
3033 cli
->dest_ss
= ss_arr
[i
];
3034 if (getenv("LIBSMB_PROG")) {
3035 cli
->fd
= sock_exec(getenv("LIBSMB_PROG"));
3037 uint16_t port
= cli
->port
;
3039 status
= open_smb_socket(&cli
->dest_ss
, &port
,
3040 cli
->timeout
, &cli
->fd
);
3041 if (NT_STATUS_IS_OK(status
)) {
3045 if (cli
->fd
== -1) {
3046 char addr
[INET6_ADDRSTRLEN
];
3047 print_sockaddr(addr
, sizeof(addr
), &ss_arr
[i
]);
3048 DEBUG(2,("Error connecting to %s (%s)\n",
3049 dest_ss
?addr
:host
,strerror(errno
)));
3051 /* Exit from loop on first connection. */
3056 if (cli
->fd
== -1) {
3058 return map_nt_error_from_unix(errno
);
3062 *dest_ss
= cli
->dest_ss
;
3065 set_socket_options(cli
->fd
, lp_socket_options());
3068 return NT_STATUS_OK
;
3072 establishes a connection to after the negprot.
3073 @param output_cli A fully initialised cli structure, non-null only on success
3074 @param dest_host The netbios name of the remote host
3075 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3076 @param port (optional) The destination port (0 for default)
3078 NTSTATUS
cli_start_connection(struct cli_state
**output_cli
,
3079 const char *my_name
,
3080 const char *dest_host
,
3081 struct sockaddr_storage
*dest_ss
, int port
,
3082 int signing_state
, int flags
)
3085 struct nmb_name calling
;
3086 struct nmb_name called
;
3087 struct cli_state
*cli
;
3088 struct sockaddr_storage ss
;
3091 my_name
= global_myname();
3093 if (!(cli
= cli_initialise_ex(signing_state
))) {
3094 return NT_STATUS_NO_MEMORY
;
3097 make_nmb_name(&calling
, my_name
, 0x0);
3098 make_nmb_name(&called
, dest_host
, 0x20);
3100 cli_set_port(cli
, port
);
3101 cli_set_timeout(cli
, 10000); /* 10 seconds. */
3111 DEBUG(3,("Connecting to host=%s\n", dest_host
));
3113 nt_status
= cli_connect(cli
, dest_host
, &ss
);
3114 if (!NT_STATUS_IS_OK(nt_status
)) {
3115 char addr
[INET6_ADDRSTRLEN
];
3116 print_sockaddr(addr
, sizeof(addr
), &ss
);
3117 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
3118 nmb_namestr(&called
), addr
, nt_errstr(nt_status
) ));
3123 if (!cli_session_request(cli
, &calling
, &called
)) {
3125 DEBUG(1,("session request to %s failed (%s)\n",
3126 called
.name
, cli_errstr(cli
)));
3127 if ((p
=strchr(called
.name
, '.')) && !is_ipaddress(called
.name
)) {
3131 if (strcmp(called
.name
, STAR_SMBSERVER
)) {
3132 make_nmb_name(&called
, STAR_SMBSERVER
, 0x20);
3135 return NT_STATUS_BAD_NETWORK_NAME
;
3138 if (flags
& CLI_FULL_CONNECTION_DONT_SPNEGO
)
3139 cli
->use_spnego
= False
;
3140 else if (flags
& CLI_FULL_CONNECTION_USE_KERBEROS
)
3141 cli
->use_kerberos
= True
;
3143 if ((flags
& CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS
) &&
3144 cli
->use_kerberos
) {
3145 cli
->fallback_after_kerberos
= true;
3147 if (flags
& CLI_FULL_CONNECTION_USE_CCACHE
) {
3148 cli
->use_ccache
= true;
3151 nt_status
= cli_negprot(cli
);
3152 if (!NT_STATUS_IS_OK(nt_status
)) {
3153 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status
)));
3159 return NT_STATUS_OK
;
3164 establishes a connection right up to doing tconX, password specified.
3165 @param output_cli A fully initialised cli structure, non-null only on success
3166 @param dest_host The netbios name of the remote host
3167 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3168 @param port (optional) The destination port (0 for default)
3169 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3170 @param service_type The 'type' of serivice.
3171 @param user Username, unix string
3172 @param domain User's domain
3173 @param password User's password, unencrypted unix string.
3176 NTSTATUS
cli_full_connection(struct cli_state
**output_cli
,
3177 const char *my_name
,
3178 const char *dest_host
,
3179 struct sockaddr_storage
*dest_ss
, int port
,
3180 const char *service
, const char *service_type
,
3181 const char *user
, const char *domain
,
3182 const char *password
, int flags
,
3186 struct cli_state
*cli
= NULL
;
3187 int pw_len
= password
? strlen(password
)+1 : 0;
3191 if (password
== NULL
) {
3195 nt_status
= cli_start_connection(&cli
, my_name
, dest_host
,
3196 dest_ss
, port
, signing_state
,
3199 if (!NT_STATUS_IS_OK(nt_status
)) {
3203 cli
->use_oplocks
= ((flags
& CLI_FULL_CONNECTION_OPLOCKS
) != 0);
3204 cli
->use_level_II_oplocks
=
3205 ((flags
& CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS
) != 0);
3207 nt_status
= cli_session_setup(cli
, user
, password
, pw_len
, password
,
3209 if (!NT_STATUS_IS_OK(nt_status
)) {
3211 if (!(flags
& CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK
)) {
3212 DEBUG(1,("failed session setup with %s\n",
3213 nt_errstr(nt_status
)));
3218 nt_status
= cli_session_setup(cli
, "", "", 0, "", 0, domain
);
3219 if (!NT_STATUS_IS_OK(nt_status
)) {
3220 DEBUG(1,("anonymous failed session setup with %s\n",
3221 nt_errstr(nt_status
)));
3228 nt_status
= cli_tcon_andx(cli
, service
, service_type
, password
,
3230 if (!NT_STATUS_IS_OK(nt_status
)) {
3231 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status
)));
3233 if (NT_STATUS_IS_OK(nt_status
)) {
3234 nt_status
= NT_STATUS_UNSUCCESSFUL
;
3240 nt_status
= cli_init_creds(cli
, user
, domain
, password
);
3241 if (!NT_STATUS_IS_OK(nt_status
)) {
3247 return NT_STATUS_OK
;
3250 /****************************************************************************
3251 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
3252 ****************************************************************************/
3254 bool attempt_netbios_session_request(struct cli_state
**ppcli
, const char *srchost
, const char *desthost
,
3255 struct sockaddr_storage
*pdest_ss
)
3257 struct nmb_name calling
, called
;
3259 make_nmb_name(&calling
, srchost
, 0x0);
3262 * If the called name is an IP address
3263 * then use *SMBSERVER immediately.
3266 if(is_ipaddress(desthost
)) {
3267 make_nmb_name(&called
, STAR_SMBSERVER
, 0x20);
3269 make_nmb_name(&called
, desthost
, 0x20);
3272 if (!cli_session_request(*ppcli
, &calling
, &called
)) {
3274 struct nmb_name smbservername
;
3276 make_nmb_name(&smbservername
, STAR_SMBSERVER
, 0x20);
3279 * If the name wasn't *SMBSERVER then
3280 * try with *SMBSERVER if the first name fails.
3283 if (nmb_name_equal(&called
, &smbservername
)) {
3286 * The name used was *SMBSERVER, don't bother with another name.
3289 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
3290 with error %s.\n", desthost
, cli_errstr(*ppcli
) ));
3295 cli_shutdown(*ppcli
);
3297 *ppcli
= cli_initialise();
3299 /* Out of memory... */
3303 status
= cli_connect(*ppcli
, desthost
, pdest_ss
);
3304 if (!NT_STATUS_IS_OK(status
) ||
3305 !cli_session_request(*ppcli
, &calling
, &smbservername
)) {
3306 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
3307 name *SMBSERVER with error %s\n", desthost
, cli_errstr(*ppcli
) ));
3315 /****************************************************************************
3316 Send an old style tcon.
3317 ****************************************************************************/
3318 NTSTATUS
cli_raw_tcon(struct cli_state
*cli
,
3319 const char *service
, const char *pass
, const char *dev
,
3320 uint16
*max_xmit
, uint16
*tid
)
3322 struct tevent_req
*req
;
3327 if (!lp_client_plaintext_auth() && (*pass
)) {
3328 DEBUG(1, ("Server requested plaintext password but 'client "
3329 "plaintext auth' is disabled\n"));
3330 return NT_STATUS_ACCESS_DENIED
;
3333 bytes
= talloc_array(talloc_tos(), uint8_t, 0);
3334 bytes
= smb_bytes_push_bytes(bytes
, 4, NULL
, 0);
3335 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
3336 service
, strlen(service
)+1, NULL
);
3337 bytes
= smb_bytes_push_bytes(bytes
, 4, NULL
, 0);
3338 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
3339 pass
, strlen(pass
)+1, NULL
);
3340 bytes
= smb_bytes_push_bytes(bytes
, 4, NULL
, 0);
3341 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
3342 dev
, strlen(dev
)+1, NULL
);
3344 status
= cli_smb(talloc_tos(), cli
, SMBtcon
, 0, 0, NULL
,
3345 talloc_get_size(bytes
), bytes
, &req
,
3346 2, NULL
, &ret_vwv
, NULL
, NULL
);
3347 if (!NT_STATUS_IS_OK(status
)) {
3351 *max_xmit
= SVAL(ret_vwv
+ 0, 0);
3352 *tid
= SVAL(ret_vwv
+ 1, 0);
3354 return NT_STATUS_OK
;
3357 /* Return a cli_state pointing at the IPC$ share for the given server */
3359 struct cli_state
*get_ipc_connect(char *server
,
3360 struct sockaddr_storage
*server_ss
,
3361 const struct user_auth_info
*user_info
)
3363 struct cli_state
*cli
;
3365 uint32_t flags
= CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK
;
3367 if (user_info
->use_kerberos
) {
3368 flags
|= CLI_FULL_CONNECTION_USE_KERBEROS
;
3371 nt_status
= cli_full_connection(&cli
, NULL
, server
, server_ss
, 0, "IPC$", "IPC",
3372 user_info
->username
? user_info
->username
: "",
3374 user_info
->password
? user_info
->password
: "",
3378 if (NT_STATUS_IS_OK(nt_status
)) {
3380 } else if (is_ipaddress(server
)) {
3381 /* windows 9* needs a correct NMB name for connections */
3382 fstring remote_name
;
3384 if (name_status_find("*", 0, 0, server_ss
, remote_name
)) {
3385 cli
= get_ipc_connect(remote_name
, server_ss
, user_info
);
3394 * Given the IP address of a master browser on the network, return its
3395 * workgroup and connect to it.
3397 * This function is provided to allow additional processing beyond what
3398 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3399 * browsers and obtain each master browsers' list of domains (in case the
3400 * first master browser is recently on the network and has not yet
3401 * synchronized with other master browsers and therefore does not yet have the
3402 * entire network browse list)
3405 struct cli_state
*get_ipc_connect_master_ip(TALLOC_CTX
*ctx
,
3406 struct ip_service
*mb_ip
,
3407 const struct user_auth_info
*user_info
,
3408 char **pp_workgroup_out
)
3410 char addr
[INET6_ADDRSTRLEN
];
3412 struct cli_state
*cli
;
3413 struct sockaddr_storage server_ss
;
3415 *pp_workgroup_out
= NULL
;
3417 print_sockaddr(addr
, sizeof(addr
), &mb_ip
->ss
);
3418 DEBUG(99, ("Looking up name of master browser %s\n",
3422 * Do a name status query to find out the name of the master browser.
3423 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3424 * master browser will not respond to a wildcard query (or, at least,
3425 * an NT4 server acting as the domain master browser will not).
3427 * We might be able to use ONLY the query on MSBROWSE, but that's not
3428 * yet been tested with all Windows versions, so until it is, leave
3429 * the original wildcard query as the first choice and fall back to
3430 * MSBROWSE if the wildcard query fails.
3432 if (!name_status_find("*", 0, 0x1d, &mb_ip
->ss
, name
) &&
3433 !name_status_find(MSBROWSE
, 1, 0x1d, &mb_ip
->ss
, name
)) {
3435 DEBUG(99, ("Could not retrieve name status for %s\n",
3440 if (!find_master_ip(name
, &server_ss
)) {
3441 DEBUG(99, ("Could not find master ip for %s\n", name
));
3445 *pp_workgroup_out
= talloc_strdup(ctx
, name
);
3447 DEBUG(4, ("found master browser %s, %s\n", name
, addr
));
3449 print_sockaddr(addr
, sizeof(addr
), &server_ss
);
3450 cli
= get_ipc_connect(addr
, &server_ss
, user_info
);
3456 * Return the IP address and workgroup of a master browser on the network, and
3460 struct cli_state
*get_ipc_connect_master_ip_bcast(TALLOC_CTX
*ctx
,
3461 const struct user_auth_info
*user_info
,
3462 char **pp_workgroup_out
)
3464 struct ip_service
*ip_list
;
3465 struct cli_state
*cli
;
3468 *pp_workgroup_out
= NULL
;
3470 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3472 /* Go looking for workgroups by broadcasting on the local network */
3474 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE
, 1, &ip_list
,
3476 DEBUG(99, ("No master browsers responded\n"));
3480 for (i
= 0; i
< count
; i
++) {
3481 char addr
[INET6_ADDRSTRLEN
];
3482 print_sockaddr(addr
, sizeof(addr
), &ip_list
[i
].ss
);
3483 DEBUG(99, ("Found master browser %s\n", addr
));
3485 cli
= get_ipc_connect_master_ip(ctx
, &ip_list
[i
],
3486 user_info
, pp_workgroup_out
);