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 "popt_common.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../libcli/auth/spnego.h"
29 #include "../libcli/auth/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"
40 {PROTOCOL_CORE
, "PC NETWORK PROGRAM 1.0"},
41 {PROTOCOL_COREPLUS
, "MICROSOFT NETWORKS 1.03"},
42 {PROTOCOL_LANMAN1
, "MICROSOFT NETWORKS 3.0"},
43 {PROTOCOL_LANMAN1
, "LANMAN1.0"},
44 {PROTOCOL_LANMAN2
, "LM1.2X002"},
45 {PROTOCOL_LANMAN2
, "DOS LANMAN2.1"},
46 {PROTOCOL_LANMAN2
, "LANMAN2.1"},
47 {PROTOCOL_LANMAN2
, "Samba"},
48 {PROTOCOL_NT1
, "NT LANMAN 1.0"},
49 {PROTOCOL_NT1
, "NT LM 0.12"},
52 #define STAR_SMBSERVER "*SMBSERVER"
54 /********************************************************
55 Utility function to ensure we always return at least
56 a valid char * pointer to an empty string for the
57 cli->server_os, cli->server_type and cli->server_domain
59 *******************************************************/
61 static NTSTATUS
smb_bytes_talloc_string(struct cli_state
*cli
,
68 *destlen
= clistr_pull_talloc(cli
,
70 SVAL(inbuf
, smb_flg2
),
76 return NT_STATUS_NO_MEMORY
;
80 *dest
= talloc_strdup(cli
, "");
82 return NT_STATUS_NO_MEMORY
;
89 * Set the user session key for a connection
90 * @param cli The cli structure to add it too
91 * @param session_key The session key used. (A copy of this is taken for the cli struct)
95 static void cli_set_session_key (struct cli_state
*cli
, const DATA_BLOB session_key
)
97 cli
->user_session_key
= data_blob(session_key
.data
, session_key
.length
);
100 /****************************************************************************
101 Do an old lanman2 style session setup.
102 ****************************************************************************/
104 struct cli_session_setup_lanman2_state
{
105 struct cli_state
*cli
;
110 static void cli_session_setup_lanman2_done(struct tevent_req
*subreq
);
112 static struct tevent_req
*cli_session_setup_lanman2_send(
113 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
114 struct cli_state
*cli
, const char *user
,
115 const char *pass
, size_t passlen
,
116 const char *workgroup
)
118 struct tevent_req
*req
, *subreq
;
119 struct cli_session_setup_lanman2_state
*state
;
120 DATA_BLOB lm_response
= data_blob_null
;
125 req
= tevent_req_create(mem_ctx
, &state
,
126 struct cli_session_setup_lanman2_state
);
135 * LANMAN servers predate NT status codes and Unicode and
136 * ignore those smb flags so we must disable the corresponding
137 * default capabilities that would otherwise cause the Unicode
138 * and NT Status flags to be set (and even returned by the
142 cli
->capabilities
&= ~(CAP_UNICODE
| CAP_STATUS32
);
145 * if in share level security then don't send a password now
147 if (!(cli
->sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
)) {
152 && (cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
)
155 * Encrypted mode needed, and non encrypted password
158 lm_response
= data_blob(NULL
, 24);
159 if (tevent_req_nomem(lm_response
.data
, req
)) {
160 return tevent_req_post(req
, ev
);
163 if (!SMBencrypt(pass
, cli
->secblob
.data
,
164 (uint8_t *)lm_response
.data
)) {
165 DEBUG(1, ("Password is > 14 chars in length, and is "
166 "therefore incompatible with Lanman "
167 "authentication\n"));
168 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
169 return tevent_req_post(req
, ev
);
171 } else if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
)
174 * Encrypted mode needed, and encrypted password
177 lm_response
= data_blob(pass
, passlen
);
178 if (tevent_req_nomem(lm_response
.data
, req
)) {
179 return tevent_req_post(req
, ev
);
181 } else if (passlen
> 0) {
183 size_t converted_size
;
185 * Plaintext mode needed, assume plaintext supplied.
187 buf
= talloc_array(talloc_tos(), uint8_t, 0);
188 buf
= smb_bytes_push_str(buf
, cli_ucs2(cli
), pass
, passlen
+1,
190 if (tevent_req_nomem(buf
, req
)) {
191 return tevent_req_post(req
, ev
);
193 lm_response
= data_blob(pass
, passlen
);
195 if (tevent_req_nomem(lm_response
.data
, req
)) {
196 return tevent_req_post(req
, ev
);
200 SCVAL(vwv
+0, 0, 0xff);
203 SSVAL(vwv
+2, 0, CLI_BUFFER_SIZE
);
206 SIVAL(vwv
+5, 0, cli
->sesskey
);
207 SSVAL(vwv
+7, 0, lm_response
.length
);
209 bytes
= talloc_array(state
, uint8_t, lm_response
.length
);
210 if (tevent_req_nomem(bytes
, req
)) {
211 return tevent_req_post(req
, ev
);
213 if (lm_response
.length
!= 0) {
214 memcpy(bytes
, lm_response
.data
, lm_response
.length
);
216 data_blob_free(&lm_response
);
218 tmp
= talloc_strdup_upper(talloc_tos(), user
);
219 if (tevent_req_nomem(tmp
, req
)) {
220 return tevent_req_post(req
, ev
);
222 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), tmp
, strlen(tmp
)+1,
226 tmp
= talloc_strdup_upper(talloc_tos(), workgroup
);
227 if (tevent_req_nomem(tmp
, req
)) {
228 return tevent_req_post(req
, ev
);
230 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), tmp
, strlen(tmp
)+1,
232 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "Unix", 5, NULL
);
233 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "Samba", 6, NULL
);
235 if (tevent_req_nomem(bytes
, req
)) {
236 return tevent_req_post(req
, ev
);
239 subreq
= cli_smb_send(state
, ev
, cli
, SMBsesssetupX
, 0, 10, vwv
,
240 talloc_get_size(bytes
), bytes
);
241 if (tevent_req_nomem(subreq
, req
)) {
242 return tevent_req_post(req
, ev
);
244 tevent_req_set_callback(subreq
, cli_session_setup_lanman2_done
, req
);
248 static void cli_session_setup_lanman2_done(struct tevent_req
*subreq
)
250 struct tevent_req
*req
= tevent_req_callback_data(
251 subreq
, struct tevent_req
);
252 struct cli_session_setup_lanman2_state
*state
= tevent_req_data(
253 req
, struct cli_session_setup_lanman2_state
);
254 struct cli_state
*cli
= state
->cli
;
265 status
= cli_smb_recv(subreq
, state
, &in
, 3, &wct
, &vwv
,
268 if (!NT_STATUS_IS_OK(status
)) {
269 tevent_req_nterror(req
, status
);
276 cli
->vuid
= SVAL(inbuf
, smb_uid
);
277 cli
->is_guestlogin
= ((SVAL(vwv
+2, 0) & 1) != 0);
279 status
= smb_bytes_talloc_string(cli
,
286 if (!NT_STATUS_IS_OK(status
)) {
287 tevent_req_nterror(req
, status
);
292 status
= smb_bytes_talloc_string(cli
,
299 if (!NT_STATUS_IS_OK(status
)) {
300 tevent_req_nterror(req
, status
);
305 status
= smb_bytes_talloc_string(cli
,
312 if (!NT_STATUS_IS_OK(status
)) {
313 tevent_req_nterror(req
, status
);
318 if (strstr(cli
->server_type
, "Samba")) {
319 cli
->is_samba
= True
;
321 status
= cli_set_username(cli
, state
->user
);
322 if (tevent_req_nterror(req
, status
)) {
325 tevent_req_done(req
);
328 static NTSTATUS
cli_session_setup_lanman2_recv(struct tevent_req
*req
)
330 return tevent_req_simple_recv_ntstatus(req
);
333 static NTSTATUS
cli_session_setup_lanman2(struct cli_state
*cli
, const char *user
,
334 const char *pass
, size_t passlen
,
335 const char *workgroup
)
337 TALLOC_CTX
*frame
= talloc_stackframe();
338 struct event_context
*ev
;
339 struct tevent_req
*req
;
340 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
342 if (cli_has_async_calls(cli
)) {
344 * Can't use sync call while an async call is in flight
346 status
= NT_STATUS_INVALID_PARAMETER
;
349 ev
= event_context_init(frame
);
353 req
= cli_session_setup_lanman2_send(frame
, ev
, cli
, user
, pass
, passlen
,
358 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
361 status
= cli_session_setup_lanman2_recv(req
);
367 /****************************************************************************
368 Work out suitable capabilities to offer the server.
369 ****************************************************************************/
371 static uint32
cli_session_setup_capabilities(struct cli_state
*cli
)
373 uint32 capabilities
= CAP_NT_SMBS
;
375 if (!cli
->force_dos_errors
)
376 capabilities
|= CAP_STATUS32
;
378 if (cli
->use_level_II_oplocks
)
379 capabilities
|= CAP_LEVEL_II_OPLOCKS
;
381 capabilities
|= (cli
->capabilities
& (CAP_UNICODE
|CAP_LARGE_FILES
|CAP_LARGE_READX
|CAP_LARGE_WRITEX
|CAP_DFS
));
385 /****************************************************************************
386 Do a NT1 guest session setup.
387 ****************************************************************************/
389 struct cli_session_setup_guest_state
{
390 struct cli_state
*cli
;
395 static void cli_session_setup_guest_done(struct tevent_req
*subreq
);
397 struct tevent_req
*cli_session_setup_guest_create(TALLOC_CTX
*mem_ctx
,
398 struct event_context
*ev
,
399 struct cli_state
*cli
,
400 struct tevent_req
**psmbreq
)
402 struct tevent_req
*req
, *subreq
;
403 struct cli_session_setup_guest_state
*state
;
407 req
= tevent_req_create(mem_ctx
, &state
,
408 struct cli_session_setup_guest_state
);
415 SCVAL(vwv
+0, 0, 0xFF);
418 SSVAL(vwv
+2, 0, CLI_BUFFER_SIZE
);
420 SSVAL(vwv
+4, 0, cli
->pid
);
421 SIVAL(vwv
+5, 0, cli
->sesskey
);
426 SIVAL(vwv
+11, 0, cli_session_setup_capabilities(cli
));
428 bytes
= talloc_array(state
, uint8_t, 0);
430 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "", 1, /* username */
432 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "", 1, /* workgroup */
434 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "Unix", 5, NULL
);
435 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "Samba", 6, NULL
);
442 state
->bytes
.iov_base
= (void *)bytes
;
443 state
->bytes
.iov_len
= talloc_get_size(bytes
);
445 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBsesssetupX
, 0, 13, vwv
,
447 if (subreq
== NULL
) {
451 tevent_req_set_callback(subreq
, cli_session_setup_guest_done
, req
);
456 struct tevent_req
*cli_session_setup_guest_send(TALLOC_CTX
*mem_ctx
,
457 struct event_context
*ev
,
458 struct cli_state
*cli
)
460 struct tevent_req
*req
, *subreq
;
463 req
= cli_session_setup_guest_create(mem_ctx
, ev
, cli
, &subreq
);
468 status
= cli_smb_req_send(subreq
);
469 if (NT_STATUS_IS_OK(status
)) {
470 tevent_req_nterror(req
, status
);
471 return tevent_req_post(req
, ev
);
476 static void cli_session_setup_guest_done(struct tevent_req
*subreq
)
478 struct tevent_req
*req
= tevent_req_callback_data(
479 subreq
, struct tevent_req
);
480 struct cli_session_setup_guest_state
*state
= tevent_req_data(
481 req
, struct cli_session_setup_guest_state
);
482 struct cli_state
*cli
= state
->cli
;
493 status
= cli_smb_recv(subreq
, state
, &in
, 3, &wct
, &vwv
,
496 if (!NT_STATUS_IS_OK(status
)) {
497 tevent_req_nterror(req
, status
);
504 cli
->vuid
= SVAL(inbuf
, smb_uid
);
505 cli
->is_guestlogin
= ((SVAL(vwv
+2, 0) & 1) != 0);
507 status
= smb_bytes_talloc_string(cli
,
514 if (!NT_STATUS_IS_OK(status
)) {
515 tevent_req_nterror(req
, status
);
520 status
= smb_bytes_talloc_string(cli
,
527 if (!NT_STATUS_IS_OK(status
)) {
528 tevent_req_nterror(req
, status
);
533 status
= smb_bytes_talloc_string(cli
,
540 if (!NT_STATUS_IS_OK(status
)) {
541 tevent_req_nterror(req
, status
);
546 if (strstr(cli
->server_type
, "Samba")) {
547 cli
->is_samba
= True
;
550 status
= cli_set_username(cli
, "");
551 if (!NT_STATUS_IS_OK(status
)) {
552 tevent_req_nterror(req
, status
);
555 tevent_req_done(req
);
558 NTSTATUS
cli_session_setup_guest_recv(struct tevent_req
*req
)
560 return tevent_req_simple_recv_ntstatus(req
);
563 static NTSTATUS
cli_session_setup_guest(struct cli_state
*cli
)
565 TALLOC_CTX
*frame
= talloc_stackframe();
566 struct event_context
*ev
;
567 struct tevent_req
*req
;
568 NTSTATUS status
= NT_STATUS_OK
;
570 if (cli_has_async_calls(cli
)) {
572 * Can't use sync call while an async call is in flight
574 status
= NT_STATUS_INVALID_PARAMETER
;
578 ev
= event_context_init(frame
);
580 status
= NT_STATUS_NO_MEMORY
;
584 req
= cli_session_setup_guest_send(frame
, ev
, cli
);
586 status
= NT_STATUS_NO_MEMORY
;
590 if (!tevent_req_poll(req
, ev
)) {
591 status
= map_nt_error_from_unix(errno
);
595 status
= cli_session_setup_guest_recv(req
);
601 /****************************************************************************
602 Do a NT1 plaintext session setup.
603 ****************************************************************************/
605 struct cli_session_setup_plain_state
{
606 struct cli_state
*cli
;
611 static void cli_session_setup_plain_done(struct tevent_req
*subreq
);
613 static struct tevent_req
*cli_session_setup_plain_send(
614 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
615 struct cli_state
*cli
,
616 const char *user
, const char *pass
, const char *workgroup
)
618 struct tevent_req
*req
, *subreq
;
619 struct cli_session_setup_plain_state
*state
;
625 req
= tevent_req_create(mem_ctx
, &state
,
626 struct cli_session_setup_plain_state
);
634 SCVAL(vwv
+0, 0, 0xff);
637 SSVAL(vwv
+2, 0, CLI_BUFFER_SIZE
);
639 SSVAL(vwv
+4, 0, cli
->pid
);
640 SIVAL(vwv
+5, 0, cli
->sesskey
);
645 SIVAL(vwv
+11, 0, cli_session_setup_capabilities(cli
));
647 bytes
= talloc_array(state
, uint8_t, 0);
648 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), pass
, strlen(pass
)+1,
650 if (tevent_req_nomem(bytes
, req
)) {
651 return tevent_req_post(req
, ev
);
653 SSVAL(vwv
+ (cli_ucs2(cli
) ? 8 : 7), 0, passlen
);
655 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
656 user
, strlen(user
)+1, NULL
);
657 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
658 workgroup
, strlen(workgroup
)+1, NULL
);
659 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
662 version
= talloc_asprintf(talloc_tos(), "Samba %s",
663 samba_version_string());
664 if (tevent_req_nomem(version
, req
)){
665 return tevent_req_post(req
, ev
);
667 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
668 version
, strlen(version
)+1, NULL
);
669 TALLOC_FREE(version
);
671 if (tevent_req_nomem(bytes
, req
)) {
672 return tevent_req_post(req
, ev
);
675 subreq
= cli_smb_send(state
, ev
, cli
, SMBsesssetupX
, 0, 13, vwv
,
676 talloc_get_size(bytes
), bytes
);
677 if (tevent_req_nomem(subreq
, req
)) {
678 return tevent_req_post(req
, ev
);
680 tevent_req_set_callback(subreq
, cli_session_setup_plain_done
, req
);
684 static void cli_session_setup_plain_done(struct tevent_req
*subreq
)
686 struct tevent_req
*req
= tevent_req_callback_data(
687 subreq
, struct tevent_req
);
688 struct cli_session_setup_plain_state
*state
= tevent_req_data(
689 req
, struct cli_session_setup_plain_state
);
690 struct cli_state
*cli
= state
->cli
;
701 status
= cli_smb_recv(subreq
, state
, &in
, 3, &wct
, &vwv
,
704 if (tevent_req_nterror(req
, status
)) {
711 cli
->vuid
= SVAL(inbuf
, smb_uid
);
712 cli
->is_guestlogin
= ((SVAL(vwv
+2, 0) & 1) != 0);
714 status
= smb_bytes_talloc_string(cli
,
721 if (!NT_STATUS_IS_OK(status
)) {
722 tevent_req_nterror(req
, status
);
727 status
= smb_bytes_talloc_string(cli
,
734 if (!NT_STATUS_IS_OK(status
)) {
735 tevent_req_nterror(req
, status
);
740 status
= smb_bytes_talloc_string(cli
,
747 if (!NT_STATUS_IS_OK(status
)) {
748 tevent_req_nterror(req
, status
);
753 status
= cli_set_username(cli
, state
->user
);
754 if (tevent_req_nterror(req
, status
)) {
757 if (strstr(cli
->server_type
, "Samba")) {
758 cli
->is_samba
= True
;
760 tevent_req_done(req
);
763 static NTSTATUS
cli_session_setup_plain_recv(struct tevent_req
*req
)
765 return tevent_req_simple_recv_ntstatus(req
);
768 static NTSTATUS
cli_session_setup_plain(struct cli_state
*cli
,
769 const char *user
, const char *pass
,
770 const char *workgroup
)
772 TALLOC_CTX
*frame
= talloc_stackframe();
773 struct event_context
*ev
;
774 struct tevent_req
*req
;
775 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
777 if (cli_has_async_calls(cli
)) {
779 * Can't use sync call while an async call is in flight
781 status
= NT_STATUS_INVALID_PARAMETER
;
784 ev
= event_context_init(frame
);
788 req
= cli_session_setup_plain_send(frame
, ev
, cli
, user
, pass
,
793 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
796 status
= cli_session_setup_plain_recv(req
);
802 /****************************************************************************
803 do a NT1 NTLM/LM encrypted session setup - for when extended security
805 @param cli client state to create do session setup on
807 @param pass *either* cleartext password (passlen !=24) or LM response.
808 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
809 @param workgroup The user's domain.
810 ****************************************************************************/
812 struct cli_session_setup_nt1_state
{
813 struct cli_state
*cli
;
816 DATA_BLOB session_key
;
820 static void cli_session_setup_nt1_done(struct tevent_req
*subreq
);
822 static struct tevent_req
*cli_session_setup_nt1_send(
823 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
824 struct cli_state
*cli
, const char *user
,
825 const char *pass
, size_t passlen
,
826 const char *ntpass
, size_t ntpasslen
,
827 const char *workgroup
)
829 struct tevent_req
*req
, *subreq
;
830 struct cli_session_setup_nt1_state
*state
;
831 DATA_BLOB lm_response
= data_blob_null
;
832 DATA_BLOB nt_response
= data_blob_null
;
833 DATA_BLOB session_key
= data_blob_null
;
836 char *workgroup_upper
;
838 req
= tevent_req_create(mem_ctx
, &state
,
839 struct cli_session_setup_nt1_state
);
848 /* do nothing - guest login */
849 } else if (passlen
!= 24) {
850 if (lp_client_ntlmv2_auth()) {
851 DATA_BLOB server_chal
;
852 DATA_BLOB names_blob
;
854 server_chal
= data_blob(cli
->secblob
.data
,
855 MIN(cli
->secblob
.length
, 8));
856 if (tevent_req_nomem(server_chal
.data
, req
)) {
857 return tevent_req_post(req
, ev
);
861 * note that the 'workgroup' here is a best
862 * guess - we don't know the server's domain
863 * at this point. The 'server name' is also
866 names_blob
= NTLMv2_generate_names_blob(
867 NULL
, cli
->called
.name
, workgroup
);
869 if (tevent_req_nomem(names_blob
.data
, req
)) {
870 return tevent_req_post(req
, ev
);
873 if (!SMBNTLMv2encrypt(NULL
, user
, workgroup
, pass
,
874 &server_chal
, &names_blob
,
875 &lm_response
, &nt_response
,
876 NULL
, &session_key
)) {
877 data_blob_free(&names_blob
);
878 data_blob_free(&server_chal
);
880 req
, NT_STATUS_ACCESS_DENIED
);
881 return tevent_req_post(req
, ev
);
883 data_blob_free(&names_blob
);
884 data_blob_free(&server_chal
);
888 E_md4hash(pass
, nt_hash
);
891 nt_response
= data_blob_null
;
893 nt_response
= data_blob(NULL
, 24);
894 if (tevent_req_nomem(nt_response
.data
, req
)) {
895 return tevent_req_post(req
, ev
);
898 SMBNTencrypt(pass
, cli
->secblob
.data
,
901 /* non encrypted password supplied. Ignore ntpass. */
902 if (lp_client_lanman_auth()) {
904 lm_response
= data_blob(NULL
, 24);
905 if (tevent_req_nomem(lm_response
.data
, req
)) {
906 return tevent_req_post(req
, ev
);
909 if (!SMBencrypt(pass
,cli
->secblob
.data
,
912 * Oops, the LM response is
913 * invalid, just put the NT
914 * response there instead
916 data_blob_free(&lm_response
);
917 lm_response
= data_blob(
923 * LM disabled, place NT# in LM field
926 lm_response
= data_blob(
927 nt_response
.data
, nt_response
.length
);
930 if (tevent_req_nomem(lm_response
.data
, req
)) {
931 return tevent_req_post(req
, ev
);
934 session_key
= data_blob(NULL
, 16);
935 if (tevent_req_nomem(session_key
.data
, req
)) {
936 return tevent_req_post(req
, ev
);
939 E_deshash(pass
, session_key
.data
);
940 memset(&session_key
.data
[8], '\0', 8);
942 SMBsesskeygen_ntv1(nt_hash
, session_key
.data
);
945 cli_temp_set_signing(cli
);
947 /* pre-encrypted password supplied. Only used for
948 security=server, can't do
949 signing because we don't have original key */
951 lm_response
= data_blob(pass
, passlen
);
952 if (tevent_req_nomem(lm_response
.data
, req
)) {
953 return tevent_req_post(req
, ev
);
956 nt_response
= data_blob(ntpass
, ntpasslen
);
957 if (tevent_req_nomem(nt_response
.data
, req
)) {
958 return tevent_req_post(req
, ev
);
963 state
->response
= data_blob_talloc(
964 state
, lm_response
.data
, lm_response
.length
);
966 state
->response
= data_blob_talloc(
967 state
, nt_response
.data
, nt_response
.length
);
969 if (tevent_req_nomem(state
->response
.data
, req
)) {
970 return tevent_req_post(req
, ev
);
973 if (session_key
.data
) {
974 state
->session_key
= data_blob_talloc(
975 state
, session_key
.data
, session_key
.length
);
976 if (tevent_req_nomem(state
->session_key
.data
, req
)) {
977 return tevent_req_post(req
, ev
);
980 data_blob_free(&session_key
);
982 SCVAL(vwv
+0, 0, 0xff);
985 SSVAL(vwv
+2, 0, CLI_BUFFER_SIZE
);
987 SSVAL(vwv
+4, 0, cli
->pid
);
988 SIVAL(vwv
+5, 0, cli
->sesskey
);
989 SSVAL(vwv
+7, 0, lm_response
.length
);
990 SSVAL(vwv
+8, 0, nt_response
.length
);
993 SIVAL(vwv
+11, 0, cli_session_setup_capabilities(cli
));
995 bytes
= talloc_array(state
, uint8_t,
996 lm_response
.length
+ nt_response
.length
);
997 if (tevent_req_nomem(bytes
, req
)) {
998 return tevent_req_post(req
, ev
);
1000 if (lm_response
.length
!= 0) {
1001 memcpy(bytes
, lm_response
.data
, lm_response
.length
);
1003 if (nt_response
.length
!= 0) {
1004 memcpy(bytes
+ lm_response
.length
,
1005 nt_response
.data
, nt_response
.length
);
1007 data_blob_free(&lm_response
);
1008 data_blob_free(&nt_response
);
1010 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
1011 user
, strlen(user
)+1, NULL
);
1014 * Upper case here might help some NTLMv2 implementations
1016 workgroup_upper
= talloc_strdup_upper(talloc_tos(), workgroup
);
1017 if (tevent_req_nomem(workgroup_upper
, req
)) {
1018 return tevent_req_post(req
, ev
);
1020 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
1021 workgroup_upper
, strlen(workgroup_upper
)+1,
1023 TALLOC_FREE(workgroup_upper
);
1025 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "Unix", 5, NULL
);
1026 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "Samba", 6, NULL
);
1027 if (tevent_req_nomem(bytes
, req
)) {
1028 return tevent_req_post(req
, ev
);
1031 subreq
= cli_smb_send(state
, ev
, cli
, SMBsesssetupX
, 0, 13, vwv
,
1032 talloc_get_size(bytes
), bytes
);
1033 if (tevent_req_nomem(subreq
, req
)) {
1034 return tevent_req_post(req
, ev
);
1036 tevent_req_set_callback(subreq
, cli_session_setup_nt1_done
, req
);
1040 static void cli_session_setup_nt1_done(struct tevent_req
*subreq
)
1042 struct tevent_req
*req
= tevent_req_callback_data(
1043 subreq
, struct tevent_req
);
1044 struct cli_session_setup_nt1_state
*state
= tevent_req_data(
1045 req
, struct cli_session_setup_nt1_state
);
1046 struct cli_state
*cli
= state
->cli
;
1057 status
= cli_smb_recv(subreq
, state
, &in
, 3, &wct
, &vwv
,
1058 &num_bytes
, &bytes
);
1059 TALLOC_FREE(subreq
);
1060 if (!NT_STATUS_IS_OK(status
)) {
1061 tevent_req_nterror(req
, status
);
1068 cli
->vuid
= SVAL(inbuf
, smb_uid
);
1069 cli
->is_guestlogin
= ((SVAL(vwv
+2, 0) & 1) != 0);
1071 status
= smb_bytes_talloc_string(cli
,
1077 if (!NT_STATUS_IS_OK(status
)) {
1078 tevent_req_nterror(req
, status
);
1083 status
= smb_bytes_talloc_string(cli
,
1089 if (!NT_STATUS_IS_OK(status
)) {
1090 tevent_req_nterror(req
, status
);
1095 status
= smb_bytes_talloc_string(cli
,
1097 &cli
->server_domain
,
1101 if (!NT_STATUS_IS_OK(status
)) {
1102 tevent_req_nterror(req
, status
);
1107 if (strstr(cli
->server_type
, "Samba")) {
1108 cli
->is_samba
= True
;
1111 status
= cli_set_username(cli
, state
->user
);
1112 if (tevent_req_nterror(req
, status
)) {
1115 if (cli_simple_set_signing(cli
, state
->session_key
, state
->response
)
1116 && !cli_check_sign_mac(cli
, (char *)in
, 1)) {
1117 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1120 if (state
->session_key
.data
) {
1121 /* Have plaintext orginal */
1122 cli_set_session_key(cli
, state
->session_key
);
1124 tevent_req_done(req
);
1127 static NTSTATUS
cli_session_setup_nt1_recv(struct tevent_req
*req
)
1129 return tevent_req_simple_recv_ntstatus(req
);
1132 static NTSTATUS
cli_session_setup_nt1(struct cli_state
*cli
, const char *user
,
1133 const char *pass
, size_t passlen
,
1134 const char *ntpass
, size_t ntpasslen
,
1135 const char *workgroup
)
1137 TALLOC_CTX
*frame
= talloc_stackframe();
1138 struct event_context
*ev
;
1139 struct tevent_req
*req
;
1140 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1142 if (cli_has_async_calls(cli
)) {
1144 * Can't use sync call while an async call is in flight
1146 status
= NT_STATUS_INVALID_PARAMETER
;
1149 ev
= event_context_init(frame
);
1153 req
= cli_session_setup_nt1_send(frame
, ev
, cli
, user
, pass
, passlen
,
1154 ntpass
, ntpasslen
, workgroup
);
1158 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1161 status
= cli_session_setup_nt1_recv(req
);
1167 /* The following is calculated from :
1169 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
1170 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1174 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1176 struct cli_sesssetup_blob_state
{
1177 struct tevent_context
*ev
;
1178 struct cli_state
*cli
;
1180 uint16_t max_blob_size
;
1189 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state
*state
,
1190 struct tevent_req
**psubreq
);
1191 static void cli_sesssetup_blob_done(struct tevent_req
*subreq
);
1193 static struct tevent_req
*cli_sesssetup_blob_send(TALLOC_CTX
*mem_ctx
,
1194 struct tevent_context
*ev
,
1195 struct cli_state
*cli
,
1198 struct tevent_req
*req
, *subreq
;
1199 struct cli_sesssetup_blob_state
*state
;
1201 req
= tevent_req_create(mem_ctx
, &state
,
1202 struct cli_sesssetup_blob_state
);
1210 if (cli
->max_xmit
< BASE_SESSSETUP_BLOB_PACKET_SIZE
+ 1) {
1211 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1212 "(was %u, need minimum %u)\n",
1213 (unsigned int)cli
->max_xmit
,
1214 BASE_SESSSETUP_BLOB_PACKET_SIZE
));
1215 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1216 return tevent_req_post(req
, ev
);
1218 state
->max_blob_size
=
1219 MIN(cli
->max_xmit
- BASE_SESSSETUP_BLOB_PACKET_SIZE
, 0xFFFF);
1221 if (!cli_sesssetup_blob_next(state
, &subreq
)) {
1222 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
1223 return tevent_req_post(req
, ev
);
1225 tevent_req_set_callback(subreq
, cli_sesssetup_blob_done
, req
);
1229 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state
*state
,
1230 struct tevent_req
**psubreq
)
1232 struct tevent_req
*subreq
;
1235 SCVAL(state
->vwv
+0, 0, 0xFF);
1236 SCVAL(state
->vwv
+0, 1, 0);
1237 SSVAL(state
->vwv
+1, 0, 0);
1238 SSVAL(state
->vwv
+2, 0, CLI_BUFFER_SIZE
);
1239 SSVAL(state
->vwv
+3, 0, 2);
1240 SSVAL(state
->vwv
+4, 0, 1);
1241 SIVAL(state
->vwv
+5, 0, 0);
1243 thistime
= MIN(state
->blob
.length
, state
->max_blob_size
);
1244 SSVAL(state
->vwv
+7, 0, thistime
);
1246 SSVAL(state
->vwv
+8, 0, 0);
1247 SSVAL(state
->vwv
+9, 0, 0);
1248 SIVAL(state
->vwv
+10, 0,
1249 cli_session_setup_capabilities(state
->cli
)
1250 | CAP_EXTENDED_SECURITY
);
1252 state
->buf
= (uint8_t *)talloc_memdup(state
, state
->blob
.data
,
1254 if (state
->buf
== NULL
) {
1257 state
->blob
.data
+= thistime
;
1258 state
->blob
.length
-= thistime
;
1260 state
->buf
= smb_bytes_push_str(state
->buf
, cli_ucs2(state
->cli
),
1262 state
->buf
= smb_bytes_push_str(state
->buf
, cli_ucs2(state
->cli
),
1264 if (state
->buf
== NULL
) {
1267 subreq
= cli_smb_send(state
, state
->ev
, state
->cli
, SMBsesssetupX
, 0,
1269 talloc_get_size(state
->buf
), state
->buf
);
1270 if (subreq
== NULL
) {
1277 static void cli_sesssetup_blob_done(struct tevent_req
*subreq
)
1279 struct tevent_req
*req
= tevent_req_callback_data(
1280 subreq
, struct tevent_req
);
1281 struct cli_sesssetup_blob_state
*state
= tevent_req_data(
1282 req
, struct cli_sesssetup_blob_state
);
1283 struct cli_state
*cli
= state
->cli
;
1290 uint16_t blob_length
;
1294 status
= cli_smb_recv(subreq
, state
, &inbuf
, 4, &wct
, &vwv
,
1295 &num_bytes
, &bytes
);
1296 TALLOC_FREE(subreq
);
1297 if (!NT_STATUS_IS_OK(status
)
1298 && !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1299 tevent_req_nterror(req
, status
);
1303 state
->status
= status
;
1304 TALLOC_FREE(state
->buf
);
1306 state
->inbuf
= (char *)inbuf
;
1307 cli
->vuid
= SVAL(state
->inbuf
, smb_uid
);
1308 cli
->is_guestlogin
= ((SVAL(vwv
+2, 0) & 1) != 0);
1310 blob_length
= SVAL(vwv
+3, 0);
1311 if (blob_length
> num_bytes
) {
1312 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
1315 state
->ret_blob
= data_blob_const(bytes
, blob_length
);
1317 p
= bytes
+ blob_length
;
1319 status
= smb_bytes_talloc_string(cli
,
1326 if (!NT_STATUS_IS_OK(status
)) {
1327 tevent_req_nterror(req
, status
);
1332 status
= smb_bytes_talloc_string(cli
,
1339 if (!NT_STATUS_IS_OK(status
)) {
1340 tevent_req_nterror(req
, status
);
1345 status
= smb_bytes_talloc_string(cli
,
1347 &cli
->server_domain
,
1352 if (!NT_STATUS_IS_OK(status
)) {
1353 tevent_req_nterror(req
, status
);
1358 if (strstr(cli
->server_type
, "Samba")) {
1359 cli
->is_samba
= True
;
1362 if (state
->blob
.length
!= 0) {
1366 if (!cli_sesssetup_blob_next(state
, &subreq
)) {
1367 tevent_req_nomem(NULL
, req
);
1370 tevent_req_set_callback(subreq
, cli_sesssetup_blob_done
, req
);
1373 tevent_req_done(req
);
1376 static NTSTATUS
cli_sesssetup_blob_recv(struct tevent_req
*req
,
1377 TALLOC_CTX
*mem_ctx
,
1381 struct cli_sesssetup_blob_state
*state
= tevent_req_data(
1382 req
, struct cli_sesssetup_blob_state
);
1386 if (tevent_req_is_nterror(req
, &status
)) {
1387 state
->cli
->vuid
= 0;
1391 inbuf
= talloc_move(mem_ctx
, &state
->inbuf
);
1392 if (pblob
!= NULL
) {
1393 *pblob
= state
->ret_blob
;
1395 if (pinbuf
!= NULL
) {
1398 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1399 return state
->status
;
1404 /****************************************************************************
1405 Use in-memory credentials cache
1406 ****************************************************************************/
1408 static void use_in_memory_ccache(void) {
1409 setenv(KRB5_ENV_CCNAME
, "MEMORY:cliconnect", 1);
1412 /****************************************************************************
1413 Do a spnego/kerberos encrypted session setup.
1414 ****************************************************************************/
1416 struct cli_session_setup_kerberos_state
{
1417 struct cli_state
*cli
;
1418 DATA_BLOB negTokenTarg
;
1419 DATA_BLOB session_key_krb5
;
1420 ADS_STATUS ads_status
;
1423 static void cli_session_setup_kerberos_done(struct tevent_req
*subreq
);
1425 static struct tevent_req
*cli_session_setup_kerberos_send(
1426 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
, struct cli_state
*cli
,
1427 const char *principal
, const char *workgroup
)
1429 struct tevent_req
*req
, *subreq
;
1430 struct cli_session_setup_kerberos_state
*state
;
1433 DEBUG(2,("Doing kerberos session setup\n"));
1435 req
= tevent_req_create(mem_ctx
, &state
,
1436 struct cli_session_setup_kerberos_state
);
1441 state
->ads_status
= ADS_SUCCESS
;
1443 cli_temp_set_signing(cli
);
1446 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1447 * we have to acquire a ticket. To be fixed later :-)
1449 rc
= spnego_gen_krb5_negTokenInit(state
, principal
, 0, &state
->negTokenTarg
,
1450 &state
->session_key_krb5
, 0, NULL
);
1452 DEBUG(1, ("cli_session_setup_kerberos: "
1453 "spnego_gen_krb5_negTokenInit failed: %s\n",
1454 error_message(rc
)));
1455 state
->ads_status
= ADS_ERROR_KRB5(rc
);
1456 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
1457 return tevent_req_post(req
, ev
);
1461 file_save("negTokenTarg.dat", state
->negTokenTarg
.data
,
1462 state
->negTokenTarg
.length
);
1465 subreq
= cli_sesssetup_blob_send(state
, ev
, cli
, state
->negTokenTarg
);
1466 if (tevent_req_nomem(subreq
, req
)) {
1467 return tevent_req_post(req
, ev
);
1469 tevent_req_set_callback(subreq
, cli_session_setup_kerberos_done
, req
);
1473 static void cli_session_setup_kerberos_done(struct tevent_req
*subreq
)
1475 struct tevent_req
*req
= tevent_req_callback_data(
1476 subreq
, struct tevent_req
);
1477 struct cli_session_setup_kerberos_state
*state
= tevent_req_data(
1478 req
, struct cli_session_setup_kerberos_state
);
1482 status
= cli_sesssetup_blob_recv(subreq
, talloc_tos(), NULL
, &inbuf
);
1483 if (!NT_STATUS_IS_OK(status
)) {
1484 TALLOC_FREE(subreq
);
1485 tevent_req_nterror(req
, status
);
1489 cli_set_session_key(state
->cli
, state
->session_key_krb5
);
1491 if (cli_simple_set_signing(state
->cli
, state
->session_key_krb5
,
1493 && !cli_check_sign_mac(state
->cli
, inbuf
, 1)) {
1494 TALLOC_FREE(subreq
);
1495 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1498 TALLOC_FREE(subreq
);
1499 tevent_req_done(req
);
1502 static ADS_STATUS
cli_session_setup_kerberos_recv(struct tevent_req
*req
)
1504 struct cli_session_setup_kerberos_state
*state
= tevent_req_data(
1505 req
, struct cli_session_setup_kerberos_state
);
1508 if (tevent_req_is_nterror(req
, &status
)) {
1509 return ADS_ERROR_NT(status
);
1511 return state
->ads_status
;
1514 static ADS_STATUS
cli_session_setup_kerberos(struct cli_state
*cli
,
1515 const char *principal
,
1516 const char *workgroup
)
1518 struct tevent_context
*ev
;
1519 struct tevent_req
*req
;
1520 ADS_STATUS status
= ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
1522 if (cli_has_async_calls(cli
)) {
1523 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
1525 ev
= tevent_context_init(talloc_tos());
1529 req
= cli_session_setup_kerberos_send(ev
, ev
, cli
, principal
,
1534 if (!tevent_req_poll(req
, ev
)) {
1535 status
= ADS_ERROR_SYSTEM(errno
);
1538 status
= cli_session_setup_kerberos_recv(req
);
1543 #endif /* HAVE_KRB5 */
1545 /****************************************************************************
1546 Do a spnego/NTLMSSP encrypted session setup.
1547 ****************************************************************************/
1549 struct cli_session_setup_ntlmssp_state
{
1550 struct tevent_context
*ev
;
1551 struct cli_state
*cli
;
1552 struct ntlmssp_state
*ntlmssp_state
;
1557 static int cli_session_setup_ntlmssp_state_destructor(
1558 struct cli_session_setup_ntlmssp_state
*state
)
1560 if (state
->ntlmssp_state
!= NULL
) {
1561 TALLOC_FREE(state
->ntlmssp_state
);
1566 static void cli_session_setup_ntlmssp_done(struct tevent_req
*req
);
1568 static struct tevent_req
*cli_session_setup_ntlmssp_send(
1569 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
, struct cli_state
*cli
,
1570 const char *user
, const char *pass
, const char *domain
)
1572 struct tevent_req
*req
, *subreq
;
1573 struct cli_session_setup_ntlmssp_state
*state
;
1576 const char *OIDs_ntlm
[] = {OID_NTLMSSP
, NULL
};
1578 req
= tevent_req_create(mem_ctx
, &state
,
1579 struct cli_session_setup_ntlmssp_state
);
1587 state
->ntlmssp_state
= NULL
;
1588 talloc_set_destructor(
1589 state
, cli_session_setup_ntlmssp_state_destructor
);
1591 cli_temp_set_signing(cli
);
1593 status
= ntlmssp_client_start(state
,
1596 lp_client_ntlmv2_auth(),
1597 &state
->ntlmssp_state
);
1598 if (!NT_STATUS_IS_OK(status
)) {
1601 ntlmssp_want_feature(state
->ntlmssp_state
,
1602 NTLMSSP_FEATURE_SESSION_KEY
);
1603 if (cli
->use_ccache
) {
1604 ntlmssp_want_feature(state
->ntlmssp_state
,
1605 NTLMSSP_FEATURE_CCACHE
);
1607 status
= ntlmssp_set_username(state
->ntlmssp_state
, user
);
1608 if (!NT_STATUS_IS_OK(status
)) {
1611 status
= ntlmssp_set_domain(state
->ntlmssp_state
, domain
);
1612 if (!NT_STATUS_IS_OK(status
)) {
1615 status
= ntlmssp_set_password(state
->ntlmssp_state
, pass
);
1616 if (!NT_STATUS_IS_OK(status
)) {
1619 status
= ntlmssp_update(state
->ntlmssp_state
, data_blob_null
,
1621 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1625 state
->blob_out
= spnego_gen_negTokenInit(state
, OIDs_ntlm
, &blob_out
, NULL
);
1626 data_blob_free(&blob_out
);
1628 subreq
= cli_sesssetup_blob_send(state
, ev
, cli
, state
->blob_out
);
1629 if (tevent_req_nomem(subreq
, req
)) {
1630 return tevent_req_post(req
, ev
);
1632 tevent_req_set_callback(subreq
, cli_session_setup_ntlmssp_done
, req
);
1635 tevent_req_nterror(req
, status
);
1636 return tevent_req_post(req
, ev
);
1639 static void cli_session_setup_ntlmssp_done(struct tevent_req
*subreq
)
1641 struct tevent_req
*req
= tevent_req_callback_data(
1642 subreq
, struct tevent_req
);
1643 struct cli_session_setup_ntlmssp_state
*state
= tevent_req_data(
1644 req
, struct cli_session_setup_ntlmssp_state
);
1645 DATA_BLOB blob_in
, msg_in
, blob_out
;
1650 status
= cli_sesssetup_blob_recv(subreq
, talloc_tos(), &blob_in
,
1652 TALLOC_FREE(subreq
);
1653 data_blob_free(&state
->blob_out
);
1655 if (NT_STATUS_IS_OK(status
)) {
1656 if (state
->cli
->server_domain
[0] == '\0') {
1657 TALLOC_FREE(state
->cli
->server_domain
);
1658 state
->cli
->server_domain
= talloc_strdup(state
->cli
,
1659 state
->ntlmssp_state
->server
.netbios_domain
);
1660 if (state
->cli
->server_domain
== NULL
) {
1661 TALLOC_FREE(subreq
);
1662 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
1666 cli_set_session_key(
1667 state
->cli
, state
->ntlmssp_state
->session_key
);
1669 if (cli_simple_set_signing(
1670 state
->cli
, state
->ntlmssp_state
->session_key
,
1672 && !cli_check_sign_mac(state
->cli
, inbuf
, 1)) {
1673 TALLOC_FREE(subreq
);
1674 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1677 TALLOC_FREE(subreq
);
1678 TALLOC_FREE(state
->ntlmssp_state
);
1679 tevent_req_done(req
);
1682 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1683 tevent_req_nterror(req
, status
);
1687 if (blob_in
.length
== 0) {
1688 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
1692 if ((state
->turn
== 1)
1693 && NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1694 DATA_BLOB tmp_blob
= data_blob_null
;
1695 /* the server might give us back two challenges */
1696 parse_ret
= spnego_parse_challenge(state
, blob_in
, &msg_in
,
1698 data_blob_free(&tmp_blob
);
1700 parse_ret
= spnego_parse_auth_response(state
, blob_in
, status
,
1701 OID_NTLMSSP
, &msg_in
);
1706 DEBUG(3,("Failed to parse auth response\n"));
1707 if (NT_STATUS_IS_OK(status
)
1708 || NT_STATUS_EQUAL(status
,
1709 NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1711 req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
1716 status
= ntlmssp_update(state
->ntlmssp_state
, msg_in
, &blob_out
);
1718 if (!NT_STATUS_IS_OK(status
)
1719 && !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1720 TALLOC_FREE(subreq
);
1721 TALLOC_FREE(state
->ntlmssp_state
);
1722 tevent_req_nterror(req
, status
);
1726 state
->blob_out
= spnego_gen_auth(state
, blob_out
);
1727 TALLOC_FREE(subreq
);
1728 if (tevent_req_nomem(state
->blob_out
.data
, req
)) {
1732 subreq
= cli_sesssetup_blob_send(state
, state
->ev
, state
->cli
,
1734 if (tevent_req_nomem(subreq
, req
)) {
1737 tevent_req_set_callback(subreq
, cli_session_setup_ntlmssp_done
, req
);
1740 static NTSTATUS
cli_session_setup_ntlmssp_recv(struct tevent_req
*req
)
1742 struct cli_session_setup_ntlmssp_state
*state
= tevent_req_data(
1743 req
, struct cli_session_setup_ntlmssp_state
);
1746 if (tevent_req_is_nterror(req
, &status
)) {
1747 state
->cli
->vuid
= 0;
1750 return NT_STATUS_OK
;
1753 static NTSTATUS
cli_session_setup_ntlmssp(struct cli_state
*cli
,
1758 struct tevent_context
*ev
;
1759 struct tevent_req
*req
;
1760 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1762 if (cli_has_async_calls(cli
)) {
1763 return NT_STATUS_INVALID_PARAMETER
;
1765 ev
= tevent_context_init(talloc_tos());
1769 req
= cli_session_setup_ntlmssp_send(ev
, ev
, cli
, user
, pass
, domain
);
1773 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1776 status
= cli_session_setup_ntlmssp_recv(req
);
1782 /****************************************************************************
1783 Do a spnego encrypted session setup.
1785 user_domain: The shortname of the domain the user/machine is a member of.
1786 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1787 ****************************************************************************/
1789 ADS_STATUS
cli_session_setup_spnego(struct cli_state
*cli
, const char *user
,
1790 const char *pass
, const char *user_domain
,
1791 const char * dest_realm
)
1793 char *principal
= NULL
;
1794 char *OIDs
[ASN1_MAX_OIDS
];
1797 const char *p
= NULL
;
1798 char *account
= NULL
;
1801 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli
->secblob
.length
));
1803 /* the server might not even do spnego */
1804 if (cli
->secblob
.length
<= 16) {
1805 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1810 file_save("negprot.dat", cli
->secblob
.data
, cli
->secblob
.length
);
1813 /* there is 16 bytes of GUID before the real spnego packet starts */
1814 blob
= data_blob(cli
->secblob
.data
+16, cli
->secblob
.length
-16);
1816 /* The server sent us the first part of the SPNEGO exchange in the
1817 * negprot reply. It is WRONG to depend on the principal sent in the
1818 * negprot reply, but right now we do it. If we don't receive one,
1819 * we try to best guess, then fall back to NTLM. */
1820 if (!spnego_parse_negTokenInit(talloc_tos(), blob
, OIDs
, &principal
, NULL
) ||
1822 data_blob_free(&blob
);
1823 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
1825 data_blob_free(&blob
);
1827 /* make sure the server understands kerberos */
1828 for (i
=0;OIDs
[i
];i
++) {
1830 DEBUG(3,("got OID=%s\n", OIDs
[i
]));
1832 DEBUGADD(3,("got OID=%s\n", OIDs
[i
]));
1833 if (strcmp(OIDs
[i
], OID_KERBEROS5_OLD
) == 0 ||
1834 strcmp(OIDs
[i
], OID_KERBEROS5
) == 0) {
1835 cli
->got_kerberos_mechanism
= True
;
1837 talloc_free(OIDs
[i
]);
1840 DEBUG(3,("got principal=%s\n", principal
? principal
: "<null>"));
1842 status
= cli_set_username(cli
, user
);
1843 if (!NT_STATUS_IS_OK(status
)) {
1844 TALLOC_FREE(principal
);
1845 return ADS_ERROR_NT(status
);
1849 /* If password is set we reauthenticate to kerberos server
1850 * and do not store results */
1852 if (cli
->got_kerberos_mechanism
&& cli
->use_kerberos
) {
1855 if (pass
&& *pass
) {
1858 use_in_memory_ccache();
1859 ret
= kerberos_kinit_password(user
, pass
, 0 /* no time correction for now */, NULL
);
1862 TALLOC_FREE(principal
);
1863 DEBUG(0, ("Kinit failed: %s\n", error_message(ret
)));
1864 if (cli
->fallback_after_kerberos
)
1866 return ADS_ERROR_KRB5(ret
);
1870 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1872 if (!lp_client_use_spnego_principal() || strequal(principal
, ADS_IGNORE_PRINCIPAL
)) {
1873 TALLOC_FREE(principal
);
1876 if (principal
== NULL
&&
1877 !is_ipaddress(cli
->desthost
) &&
1878 !strequal(STAR_SMBSERVER
,
1882 DEBUG(3,("cli_session_setup_spnego: using target "
1883 "hostname not SPNEGO principal\n"));
1885 host
= strchr_m(cli
->desthost
, '.');
1887 realm
= SMB_STRDUP(dest_realm
);
1889 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
1895 realm
= kerberos_get_realm_from_hostname(cli
->desthost
);
1897 /* NetBIOS name - use our realm. */
1898 realm
= kerberos_get_default_realm_from_ccache();
1902 if (realm
== NULL
|| *realm
== '\0') {
1903 realm
= SMB_STRDUP(lp_realm());
1905 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
1908 DEBUG(3,("cli_session_setup_spnego: cannot "
1909 "get realm from dest_realm %s, "
1910 "desthost %s. Using default "
1911 "smb.conf realm %s\n",
1912 dest_realm
? dest_realm
: "<null>",
1917 principal
= talloc_asprintf(talloc_tos(),
1923 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
1925 DEBUG(3,("cli_session_setup_spnego: guessed "
1926 "server principal=%s\n",
1927 principal
? principal
: "<null>"));
1933 rc
= cli_session_setup_kerberos(cli
, principal
,
1935 if (ADS_ERR_OK(rc
) || !cli
->fallback_after_kerberos
) {
1936 TALLOC_FREE(principal
);
1943 TALLOC_FREE(principal
);
1947 account
= talloc_strdup(talloc_tos(), user
);
1949 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
1952 /* when falling back to ntlmssp while authenticating with a machine
1953 * account strip off the realm - gd */
1955 if ((p
= strchr_m(user
, '@')) != NULL
) {
1956 account
[PTR_DIFF(p
,user
)] = '\0';
1959 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli
, account
, pass
, user_domain
));
1962 /****************************************************************************
1963 Send a session setup. The username and workgroup is in UNIX character
1964 format and must be converted to DOS codepage format before sending. If the
1965 password is in plaintext, the same should be done.
1966 ****************************************************************************/
1968 NTSTATUS
cli_session_setup(struct cli_state
*cli
,
1970 const char *pass
, int passlen
,
1971 const char *ntpass
, int ntpasslen
,
1972 const char *workgroup
)
1978 user2
= talloc_strdup(talloc_tos(), user
);
1980 user2
= talloc_strdup(talloc_tos(), "");
1982 if (user2
== NULL
) {
1983 return NT_STATUS_NO_MEMORY
;
1990 /* allow for workgroups as part of the username */
1991 if ((p
=strchr_m(user2
,'\\')) || (p
=strchr_m(user2
,'/')) ||
1992 (p
=strchr_m(user2
,*lp_winbind_separator()))) {
1999 if (cli
->protocol
< PROTOCOL_LANMAN1
) {
2001 * Ensure cli->server_domain,
2002 * cli->server_os and cli->server_type
2003 * are valid pointers.
2005 cli
->server_domain
= talloc_strdup(cli
, "");
2006 cli
->server_os
= talloc_strdup(cli
, "");
2007 cli
->server_type
= talloc_strdup(cli
, "");
2008 if (cli
->server_domain
== NULL
||
2009 cli
->server_os
== NULL
||
2010 cli
->server_type
== NULL
) {
2011 return NT_STATUS_NO_MEMORY
;
2013 return NT_STATUS_OK
;
2016 /* now work out what sort of session setup we are going to
2017 do. I have split this into separate functions to make the
2018 flow a bit easier to understand (tridge) */
2020 /* if its an older server then we have to use the older request format */
2022 if (cli
->protocol
< PROTOCOL_NT1
) {
2023 if (!lp_client_lanman_auth() && passlen
!= 24 && (*pass
)) {
2024 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2025 " or 'client ntlmv2 auth = yes'\n"));
2026 return NT_STATUS_ACCESS_DENIED
;
2029 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) == 0 &&
2030 !lp_client_plaintext_auth() && (*pass
)) {
2031 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2032 " or 'client ntlmv2 auth = yes'\n"));
2033 return NT_STATUS_ACCESS_DENIED
;
2036 return cli_session_setup_lanman2(cli
, user
, pass
, passlen
,
2040 /* if no user is supplied then we have to do an anonymous connection.
2041 passwords are ignored */
2043 if (!user
|| !*user
)
2044 return cli_session_setup_guest(cli
);
2046 /* if the server is share level then send a plaintext null
2047 password at this point. The password is sent in the tree
2050 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
) == 0)
2051 return cli_session_setup_plain(cli
, user
, "", workgroup
);
2053 /* if the server doesn't support encryption then we have to use
2054 plaintext. The second password is ignored */
2056 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) == 0) {
2057 if (!lp_client_plaintext_auth() && (*pass
)) {
2058 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2059 " or 'client ntlmv2 auth = yes'\n"));
2060 return NT_STATUS_ACCESS_DENIED
;
2062 return cli_session_setup_plain(cli
, user
, pass
, workgroup
);
2065 /* if the server supports extended security then use SPNEGO */
2067 if (cli
->capabilities
& CAP_EXTENDED_SECURITY
) {
2068 ADS_STATUS status
= cli_session_setup_spnego(cli
, user
, pass
,
2070 if (!ADS_ERR_OK(status
)) {
2071 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status
)));
2072 return ads_ntstatus(status
);
2077 /* otherwise do a NT1 style session setup */
2078 status
= cli_session_setup_nt1(cli
, user
, pass
, passlen
,
2079 ntpass
, ntpasslen
, workgroup
);
2080 if (!NT_STATUS_IS_OK(status
)) {
2081 DEBUG(3,("cli_session_setup: NT1 session setup "
2082 "failed: %s\n", nt_errstr(status
)));
2087 if (strstr(cli
->server_type
, "Samba")) {
2088 cli
->is_samba
= True
;
2091 return NT_STATUS_OK
;
2094 /****************************************************************************
2096 *****************************************************************************/
2098 struct cli_ulogoff_state
{
2099 struct cli_state
*cli
;
2103 static void cli_ulogoff_done(struct tevent_req
*subreq
);
2105 struct tevent_req
*cli_ulogoff_send(TALLOC_CTX
*mem_ctx
,
2106 struct tevent_context
*ev
,
2107 struct cli_state
*cli
)
2109 struct tevent_req
*req
, *subreq
;
2110 struct cli_ulogoff_state
*state
;
2112 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ulogoff_state
);
2118 SCVAL(state
->vwv
+0, 0, 0xFF);
2119 SCVAL(state
->vwv
+1, 0, 0);
2120 SSVAL(state
->vwv
+2, 0, 0);
2122 subreq
= cli_smb_send(state
, ev
, cli
, SMBulogoffX
, 0, 2, state
->vwv
,
2124 if (tevent_req_nomem(subreq
, req
)) {
2125 return tevent_req_post(req
, ev
);
2127 tevent_req_set_callback(subreq
, cli_ulogoff_done
, req
);
2131 static void cli_ulogoff_done(struct tevent_req
*subreq
)
2133 struct tevent_req
*req
= tevent_req_callback_data(
2134 subreq
, struct tevent_req
);
2135 struct cli_ulogoff_state
*state
= tevent_req_data(
2136 req
, struct cli_ulogoff_state
);
2139 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2140 if (!NT_STATUS_IS_OK(status
)) {
2141 tevent_req_nterror(req
, status
);
2144 state
->cli
->vuid
= -1;
2145 tevent_req_done(req
);
2148 NTSTATUS
cli_ulogoff_recv(struct tevent_req
*req
)
2150 return tevent_req_simple_recv_ntstatus(req
);
2153 NTSTATUS
cli_ulogoff(struct cli_state
*cli
)
2155 struct tevent_context
*ev
;
2156 struct tevent_req
*req
;
2157 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2159 if (cli_has_async_calls(cli
)) {
2160 return NT_STATUS_INVALID_PARAMETER
;
2162 ev
= tevent_context_init(talloc_tos());
2166 req
= cli_ulogoff_send(ev
, ev
, cli
);
2170 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2173 status
= cli_ulogoff_recv(req
);
2179 /****************************************************************************
2181 ****************************************************************************/
2183 struct cli_tcon_andx_state
{
2184 struct cli_state
*cli
;
2189 static void cli_tcon_andx_done(struct tevent_req
*subreq
);
2191 struct tevent_req
*cli_tcon_andx_create(TALLOC_CTX
*mem_ctx
,
2192 struct event_context
*ev
,
2193 struct cli_state
*cli
,
2194 const char *share
, const char *dev
,
2195 const char *pass
, int passlen
,
2196 struct tevent_req
**psmbreq
)
2198 struct tevent_req
*req
, *subreq
;
2199 struct cli_tcon_andx_state
*state
;
2207 req
= tevent_req_create(mem_ctx
, &state
, struct cli_tcon_andx_state
);
2214 cli
->share
= talloc_strdup(cli
, share
);
2219 /* in user level security don't send a password now */
2220 if (cli
->sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
) {
2223 } else if (pass
== NULL
) {
2224 DEBUG(1, ("Server not using user level security and no "
2225 "password supplied.\n"));
2229 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) &&
2230 *pass
&& passlen
!= 24) {
2231 if (!lp_client_lanman_auth()) {
2232 DEBUG(1, ("Server requested LANMAN password "
2233 "(share-level security) but "
2234 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2239 * Non-encrypted passwords - convert to DOS codepage before
2242 SMBencrypt(pass
, cli
->secblob
.data
, p24
);
2244 pass
= (const char *)p24
;
2246 if((cli
->sec_mode
& (NEGOTIATE_SECURITY_USER_LEVEL
2247 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
))
2251 if (!lp_client_plaintext_auth() && (*pass
)) {
2252 DEBUG(1, ("Server requested plaintext "
2254 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2259 * Non-encrypted passwords - convert to DOS codepage
2262 tmp_pass
= talloc_array(talloc_tos(), char, 128);
2263 if (tmp_pass
== NULL
) {
2264 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
2265 return tevent_req_post(req
, ev
);
2267 passlen
= clistr_push(cli
,
2270 talloc_get_size(tmp_pass
),
2272 if (passlen
== -1) {
2273 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
2274 return tevent_req_post(req
, ev
);
2280 SCVAL(vwv
+0, 0, 0xFF);
2283 SSVAL(vwv
+2, 0, TCONX_FLAG_EXTENDED_RESPONSE
);
2284 SSVAL(vwv
+3, 0, passlen
);
2286 if (passlen
&& pass
) {
2287 bytes
= (uint8_t *)talloc_memdup(state
, pass
, passlen
);
2289 bytes
= talloc_array(state
, uint8_t, 0);
2295 tmp
= talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2296 cli
->desthost
, share
);
2301 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), tmp
, strlen(tmp
)+1,
2306 * Add the devicetype
2308 tmp
= talloc_strdup_upper(talloc_tos(), dev
);
2313 bytes
= smb_bytes_push_str(bytes
, false, tmp
, strlen(tmp
)+1, NULL
);
2316 if (bytes
== NULL
) {
2321 state
->bytes
.iov_base
= (void *)bytes
;
2322 state
->bytes
.iov_len
= talloc_get_size(bytes
);
2324 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBtconX
, 0, 4, vwv
,
2326 if (subreq
== NULL
) {
2330 tevent_req_set_callback(subreq
, cli_tcon_andx_done
, req
);
2335 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2336 return tevent_req_post(req
, ev
);
2339 struct tevent_req
*cli_tcon_andx_send(TALLOC_CTX
*mem_ctx
,
2340 struct event_context
*ev
,
2341 struct cli_state
*cli
,
2342 const char *share
, const char *dev
,
2343 const char *pass
, int passlen
)
2345 struct tevent_req
*req
, *subreq
;
2348 req
= cli_tcon_andx_create(mem_ctx
, ev
, cli
, share
, dev
, pass
, passlen
,
2353 if (subreq
== NULL
) {
2356 status
= cli_smb_req_send(subreq
);
2357 if (!NT_STATUS_IS_OK(status
)) {
2358 tevent_req_nterror(req
, status
);
2359 return tevent_req_post(req
, ev
);
2364 static void cli_tcon_andx_done(struct tevent_req
*subreq
)
2366 struct tevent_req
*req
= tevent_req_callback_data(
2367 subreq
, struct tevent_req
);
2368 struct cli_tcon_andx_state
*state
= tevent_req_data(
2369 req
, struct cli_tcon_andx_state
);
2370 struct cli_state
*cli
= state
->cli
;
2379 status
= cli_smb_recv(subreq
, state
, &in
, 0, &wct
, &vwv
,
2380 &num_bytes
, &bytes
);
2381 TALLOC_FREE(subreq
);
2382 if (!NT_STATUS_IS_OK(status
)) {
2383 tevent_req_nterror(req
, status
);
2390 if (clistr_pull_talloc(cli
,
2392 SVAL(inbuf
, smb_flg2
),
2396 STR_TERMINATE
|STR_ASCII
) == -1) {
2397 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
2401 cli
->dev
= talloc_strdup(cli
, "");
2402 if (cli
->dev
== NULL
) {
2403 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
2408 if ((cli
->protocol
>= PROTOCOL_NT1
) && (num_bytes
== 3)) {
2409 /* almost certainly win95 - enable bug fixes */
2414 * Make sure that we have the optional support 16-bit field. WCT > 2.
2415 * Avoids issues when connecting to Win9x boxes sharing files
2418 cli
->dfsroot
= false;
2420 if ((wct
> 2) && (cli
->protocol
>= PROTOCOL_LANMAN2
)) {
2421 cli
->dfsroot
= ((SVAL(vwv
+2, 0) & SMB_SHARE_IN_DFS
) != 0);
2424 cli
->cnum
= SVAL(inbuf
,smb_tid
);
2425 tevent_req_done(req
);
2428 NTSTATUS
cli_tcon_andx_recv(struct tevent_req
*req
)
2430 return tevent_req_simple_recv_ntstatus(req
);
2433 NTSTATUS
cli_tcon_andx(struct cli_state
*cli
, const char *share
,
2434 const char *dev
, const char *pass
, int passlen
)
2436 TALLOC_CTX
*frame
= talloc_stackframe();
2437 struct event_context
*ev
;
2438 struct tevent_req
*req
;
2439 NTSTATUS status
= NT_STATUS_OK
;
2441 if (cli_has_async_calls(cli
)) {
2443 * Can't use sync call while an async call is in flight
2445 status
= NT_STATUS_INVALID_PARAMETER
;
2449 ev
= event_context_init(frame
);
2451 status
= NT_STATUS_NO_MEMORY
;
2455 req
= cli_tcon_andx_send(frame
, ev
, cli
, share
, dev
, pass
, passlen
);
2457 status
= NT_STATUS_NO_MEMORY
;
2461 if (!tevent_req_poll(req
, ev
)) {
2462 status
= map_nt_error_from_unix(errno
);
2466 status
= cli_tcon_andx_recv(req
);
2472 /****************************************************************************
2473 Send a tree disconnect.
2474 ****************************************************************************/
2476 struct cli_tdis_state
{
2477 struct cli_state
*cli
;
2480 static void cli_tdis_done(struct tevent_req
*subreq
);
2482 struct tevent_req
*cli_tdis_send(TALLOC_CTX
*mem_ctx
,
2483 struct tevent_context
*ev
,
2484 struct cli_state
*cli
)
2486 struct tevent_req
*req
, *subreq
;
2487 struct cli_tdis_state
*state
;
2489 req
= tevent_req_create(mem_ctx
, &state
, struct cli_tdis_state
);
2495 subreq
= cli_smb_send(state
, ev
, cli
, SMBtdis
, 0, 0, NULL
, 0, NULL
);
2496 if (tevent_req_nomem(subreq
, req
)) {
2497 return tevent_req_post(req
, ev
);
2499 tevent_req_set_callback(subreq
, cli_tdis_done
, req
);
2503 static void cli_tdis_done(struct tevent_req
*subreq
)
2505 struct tevent_req
*req
= tevent_req_callback_data(
2506 subreq
, struct tevent_req
);
2507 struct cli_tdis_state
*state
= tevent_req_data(
2508 req
, struct cli_tdis_state
);
2511 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2512 TALLOC_FREE(subreq
);
2513 if (!NT_STATUS_IS_OK(status
)) {
2514 tevent_req_nterror(req
, status
);
2517 state
->cli
->cnum
= -1;
2518 tevent_req_done(req
);
2521 NTSTATUS
cli_tdis_recv(struct tevent_req
*req
)
2523 return tevent_req_simple_recv_ntstatus(req
);
2526 NTSTATUS
cli_tdis(struct cli_state
*cli
)
2528 struct tevent_context
*ev
;
2529 struct tevent_req
*req
;
2530 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2532 if (cli_has_async_calls(cli
)) {
2533 return NT_STATUS_INVALID_PARAMETER
;
2535 ev
= tevent_context_init(talloc_tos());
2539 req
= cli_tdis_send(ev
, ev
, cli
);
2543 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2546 status
= cli_tdis_recv(req
);
2552 /****************************************************************************
2553 Send a negprot command.
2554 ****************************************************************************/
2556 struct cli_negprot_state
{
2557 struct cli_state
*cli
;
2560 static void cli_negprot_done(struct tevent_req
*subreq
);
2562 struct tevent_req
*cli_negprot_send(TALLOC_CTX
*mem_ctx
,
2563 struct event_context
*ev
,
2564 struct cli_state
*cli
)
2566 struct tevent_req
*req
, *subreq
;
2567 struct cli_negprot_state
*state
;
2568 uint8_t *bytes
= NULL
;
2572 req
= tevent_req_create(mem_ctx
, &state
, struct cli_negprot_state
);
2578 if (cli
->protocol
< PROTOCOL_NT1
)
2579 cli
->use_spnego
= False
;
2581 /* setup the protocol strings */
2582 for (numprots
=0; numprots
< ARRAY_SIZE(prots
); numprots
++) {
2584 if (prots
[numprots
].prot
> cli
->protocol
) {
2587 bytes
= (uint8_t *)talloc_append_blob(
2588 state
, bytes
, data_blob_const(&c
, sizeof(c
)));
2589 if (tevent_req_nomem(bytes
, req
)) {
2590 return tevent_req_post(req
, ev
);
2592 bytes
= smb_bytes_push_str(bytes
, false,
2593 prots
[numprots
].name
,
2594 strlen(prots
[numprots
].name
)+1,
2596 if (tevent_req_nomem(bytes
, req
)) {
2597 return tevent_req_post(req
, ev
);
2604 subreq
= cli_smb_send(state
, ev
, cli
, SMBnegprot
, 0, 0, NULL
,
2605 talloc_get_size(bytes
), bytes
);
2608 if (tevent_req_nomem(subreq
, req
)) {
2609 return tevent_req_post(req
, ev
);
2611 tevent_req_set_callback(subreq
, cli_negprot_done
, req
);
2615 static void cli_negprot_done(struct tevent_req
*subreq
)
2617 struct tevent_req
*req
= tevent_req_callback_data(
2618 subreq
, struct tevent_req
);
2619 struct cli_negprot_state
*state
= tevent_req_data(
2620 req
, struct cli_negprot_state
);
2621 struct cli_state
*cli
= state
->cli
;
2630 status
= cli_smb_recv(subreq
, state
, &inbuf
, 1, &wct
, &vwv
,
2631 &num_bytes
, &bytes
);
2632 TALLOC_FREE(subreq
);
2633 if (!NT_STATUS_IS_OK(status
)) {
2634 tevent_req_nterror(req
, status
);
2638 protnum
= SVAL(vwv
, 0);
2640 if ((protnum
>= ARRAY_SIZE(prots
))
2641 || (prots
[protnum
].prot
> cli
->protocol
)) {
2642 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
2646 cli
->protocol
= prots
[protnum
].prot
;
2648 if ((cli
->protocol
< PROTOCOL_NT1
) &&
2649 client_is_signing_mandatory(cli
)) {
2650 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2651 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2655 if (cli
->protocol
>= PROTOCOL_NT1
) {
2657 bool negotiated_smb_signing
= false;
2658 DATA_BLOB blob
= data_blob_null
;
2661 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
2666 cli
->sec_mode
= CVAL(vwv
+ 1, 0);
2667 cli
->max_mux
= SVAL(vwv
+ 1, 1);
2668 cli
->max_xmit
= IVAL(vwv
+ 3, 1);
2669 cli
->sesskey
= IVAL(vwv
+ 7, 1);
2670 cli
->serverzone
= SVALS(vwv
+ 15, 1);
2671 cli
->serverzone
*= 60;
2672 /* this time arrives in real GMT */
2673 ts
= interpret_long_date(((char *)(vwv
+11))+1);
2674 cli
->servertime
= ts
.tv_sec
;
2675 cli
->secblob
= data_blob(bytes
, num_bytes
);
2676 cli
->capabilities
= IVAL(vwv
+ 9, 1);
2677 if (cli
->capabilities
& CAP_RAW_MODE
) {
2678 cli
->readbraw_supported
= True
;
2679 cli
->writebraw_supported
= True
;
2681 /* work out if they sent us a workgroup */
2682 if (!(cli
->capabilities
& CAP_EXTENDED_SECURITY
) &&
2683 smb_buflen(inbuf
) > 8) {
2684 blob
= data_blob_const(bytes
+ 8, num_bytes
- 8);
2687 if (blob
.length
> 0) {
2689 char *server_domain
= NULL
;
2691 ret
= clistr_pull_talloc(cli
,
2692 (const char *)inbuf
,
2693 SVAL(inbuf
, smb_flg2
),
2701 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
2704 if (server_domain
) {
2705 cli
->server_domain
= server_domain
;
2710 * As signing is slow we only turn it on if either the client or
2711 * the server require it. JRA.
2714 if (cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_REQUIRED
) {
2715 /* Fail if server says signing is mandatory and we don't want to support it. */
2716 if (!client_is_signing_allowed(cli
)) {
2717 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2718 tevent_req_nterror(req
,
2719 NT_STATUS_ACCESS_DENIED
);
2722 negotiated_smb_signing
= true;
2723 } else if (client_is_signing_mandatory(cli
) && client_is_signing_allowed(cli
)) {
2724 /* Fail if client says signing is mandatory and the server doesn't support it. */
2725 if (!(cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_ENABLED
)) {
2726 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2727 tevent_req_nterror(req
,
2728 NT_STATUS_ACCESS_DENIED
);
2731 negotiated_smb_signing
= true;
2732 } else if (cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_ENABLED
) {
2733 negotiated_smb_signing
= true;
2736 if (negotiated_smb_signing
) {
2737 cli_set_signing_negotiated(cli
);
2740 if (cli
->capabilities
& (CAP_LARGE_READX
|CAP_LARGE_WRITEX
)) {
2741 SAFE_FREE(cli
->outbuf
);
2742 SAFE_FREE(cli
->inbuf
);
2743 cli
->outbuf
= (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE
+LARGE_WRITEX_HDR_SIZE
+SAFETY_MARGIN
);
2744 cli
->inbuf
= (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE
+LARGE_WRITEX_HDR_SIZE
+SAFETY_MARGIN
);
2745 if (!cli
->outbuf
|| !cli
->inbuf
) {
2746 tevent_req_nterror(req
,
2747 NT_STATUS_NO_MEMORY
);
2750 cli
->bufsize
= CLI_SAMBA_MAX_LARGE_READX_SIZE
+ LARGE_WRITEX_HDR_SIZE
;
2753 } else if (cli
->protocol
>= PROTOCOL_LANMAN1
) {
2755 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
2759 cli
->use_spnego
= False
;
2760 cli
->sec_mode
= SVAL(vwv
+ 1, 0);
2761 cli
->max_xmit
= SVAL(vwv
+ 2, 0);
2762 cli
->max_mux
= SVAL(vwv
+ 3, 0);
2763 cli
->sesskey
= IVAL(vwv
+ 6, 0);
2764 cli
->serverzone
= SVALS(vwv
+ 10, 0);
2765 cli
->serverzone
*= 60;
2766 /* this time is converted to GMT by make_unix_date */
2767 cli
->servertime
= make_unix_date(
2768 (char *)(vwv
+ 8), cli
->serverzone
);
2769 cli
->readbraw_supported
= ((SVAL(vwv
+ 5, 0) & 0x1) != 0);
2770 cli
->writebraw_supported
= ((SVAL(vwv
+ 5, 0) & 0x2) != 0);
2771 cli
->secblob
= data_blob(bytes
, num_bytes
);
2773 /* the old core protocol */
2774 cli
->use_spnego
= False
;
2776 cli
->serverzone
= get_time_zone(time(NULL
));
2779 cli
->max_xmit
= MIN(cli
->max_xmit
, CLI_BUFFER_SIZE
);
2781 /* a way to force ascii SMB */
2782 if (getenv("CLI_FORCE_ASCII"))
2783 cli
->capabilities
&= ~CAP_UNICODE
;
2785 tevent_req_done(req
);
2788 NTSTATUS
cli_negprot_recv(struct tevent_req
*req
)
2790 return tevent_req_simple_recv_ntstatus(req
);
2793 NTSTATUS
cli_negprot(struct cli_state
*cli
)
2795 TALLOC_CTX
*frame
= talloc_stackframe();
2796 struct event_context
*ev
;
2797 struct tevent_req
*req
;
2798 NTSTATUS status
= NT_STATUS_OK
;
2800 if (cli_has_async_calls(cli
)) {
2802 * Can't use sync call while an async call is in flight
2804 status
= NT_STATUS_INVALID_PARAMETER
;
2808 ev
= event_context_init(frame
);
2810 status
= NT_STATUS_NO_MEMORY
;
2814 req
= cli_negprot_send(frame
, ev
, cli
);
2816 status
= NT_STATUS_NO_MEMORY
;
2820 if (!tevent_req_poll(req
, ev
)) {
2821 status
= map_nt_error_from_unix(errno
);
2825 status
= cli_negprot_recv(req
);
2831 /****************************************************************************
2832 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
2833 ****************************************************************************/
2835 bool cli_session_request(struct cli_state
*cli
,
2836 struct nmb_name
*calling
, struct nmb_name
*called
)
2843 /* 445 doesn't have session request */
2844 if (cli
->port
== 445)
2847 memcpy(&(cli
->calling
), calling
, sizeof(*calling
));
2848 memcpy(&(cli
->called
), called
, sizeof(*called
));
2850 /* put in the destination name */
2852 tmp
= name_mangle(talloc_tos(), cli
->called
.name
,
2853 cli
->called
.name_type
);
2858 p
= cli
->outbuf
+len
;
2859 namelen
= name_len((unsigned char *)tmp
, talloc_get_size(tmp
));
2861 memcpy(p
, tmp
, namelen
);
2868 tmp
= name_mangle(talloc_tos(), cli
->calling
.name
,
2869 cli
->calling
.name_type
);
2874 p
= cli
->outbuf
+len
;
2875 namelen
= name_len((unsigned char *)tmp
, talloc_get_size(tmp
));
2877 memcpy(p
, tmp
, namelen
);
2882 /* send a session request (RFC 1002) */
2883 /* setup the packet length
2884 * Remove four bytes from the length count, since the length
2885 * field in the NBT Session Service header counts the number
2886 * of bytes which follow. The cli_send_smb() function knows
2887 * about this and accounts for those four bytes.
2891 _smb_setlen(cli
->outbuf
,len
);
2892 SCVAL(cli
->outbuf
,0,0x81);
2895 DEBUG(5,("Sent session request\n"));
2897 if (!cli_receive_smb(cli
))
2900 if (CVAL(cli
->inbuf
,0) == 0x84) {
2901 /* C. Hoch 9/14/95 Start */
2902 /* For information, here is the response structure.
2903 * We do the byte-twiddling to for portability.
2904 struct RetargetResponse{
2906 unsigned char flags;
2912 uint16_t port
= (CVAL(cli
->inbuf
,8)<<8)+CVAL(cli
->inbuf
,9);
2913 struct in_addr dest_ip
;
2916 /* SESSION RETARGET */
2917 putip((char *)&dest_ip
,cli
->inbuf
+4);
2918 in_addr_to_sockaddr_storage(&cli
->dest_ss
, dest_ip
);
2920 status
= open_socket_out(&cli
->dest_ss
, port
,
2921 LONG_CONNECT_TIMEOUT
, &cli
->fd
);
2922 if (!NT_STATUS_IS_OK(status
)) {
2926 DEBUG(3,("Retargeted\n"));
2928 set_socket_options(cli
->fd
, lp_socket_options());
2935 DEBUG(0,("Retarget recursion - failing\n"));
2939 ret
= cli_session_request(cli
, calling
, called
);
2943 } /* C. Hoch 9/14/95 End */
2945 if (CVAL(cli
->inbuf
,0) != 0x82) {
2946 /* This is the wrong place to put the error... JRA. */
2947 cli
->rap_error
= CVAL(cli
->inbuf
,4);
2957 static void smb_sock_connected(struct tevent_req
*req
)
2959 struct fd_struct
*pfd
= tevent_req_callback_data(
2960 req
, struct fd_struct
);
2964 status
= open_socket_out_defer_recv(req
, &fd
);
2965 if (NT_STATUS_IS_OK(status
)) {
2970 static NTSTATUS
open_smb_socket(const struct sockaddr_storage
*pss
,
2971 uint16_t *port
, int timeout
, int *pfd
)
2973 struct event_context
*ev
;
2974 struct tevent_req
*r139
, *r445
;
2975 struct fd_struct
*fd139
, *fd445
;
2976 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2979 return open_socket_out(pss
, *port
, timeout
, pfd
);
2982 ev
= event_context_init(talloc_tos());
2984 return NT_STATUS_NO_MEMORY
;
2987 fd139
= talloc(ev
, struct fd_struct
);
2988 if (fd139
== NULL
) {
2993 fd445
= talloc(ev
, struct fd_struct
);
2994 if (fd445
== NULL
) {
2999 r445
= open_socket_out_defer_send(ev
, ev
, timeval_set(0, 0),
3001 r139
= open_socket_out_defer_send(ev
, ev
, timeval_set(0, 3000),
3003 if ((r445
== NULL
) || (r139
== NULL
)) {
3006 tevent_req_set_callback(r445
, smb_sock_connected
, fd445
);
3007 tevent_req_set_callback(r139
, smb_sock_connected
, fd139
);
3009 while ((fd445
->fd
== -1) && (fd139
->fd
== -1)
3010 && (tevent_req_is_in_progress(r139
)
3011 || tevent_req_is_in_progress(r445
))) {
3012 event_loop_once(ev
);
3015 if ((fd139
->fd
!= -1) && (fd445
->fd
!= -1)) {
3020 if (fd445
->fd
!= -1) {
3023 status
= NT_STATUS_OK
;
3026 if (fd139
->fd
!= -1) {
3029 status
= NT_STATUS_OK
;
3033 status
= open_socket_out_defer_recv(r445
, &fd445
->fd
);
3039 /****************************************************************************
3040 Open the client sockets.
3041 ****************************************************************************/
3043 NTSTATUS
cli_connect(struct cli_state
*cli
,
3045 struct sockaddr_storage
*dest_ss
)
3048 int name_type
= 0x20;
3049 TALLOC_CTX
*frame
= talloc_stackframe();
3050 unsigned int num_addrs
= 0;
3052 struct sockaddr_storage
*ss_arr
= NULL
;
3055 /* reasonable default hostname */
3057 host
= STAR_SMBSERVER
;
3060 cli
->desthost
= talloc_strdup(cli
, host
);
3061 if (cli
->desthost
== NULL
) {
3062 return NT_STATUS_NO_MEMORY
;
3065 /* allow hostnames of the form NAME#xx and do a netbios lookup */
3066 if ((p
= strchr(cli
->desthost
, '#'))) {
3067 name_type
= strtol(p
+1, NULL
, 16);
3071 if (!dest_ss
|| is_zero_addr(dest_ss
)) {
3072 NTSTATUS status
=resolve_name_list(frame
,
3077 if (!NT_STATUS_IS_OK(status
)) {
3079 return NT_STATUS_BAD_NETWORK_NAME
;
3083 ss_arr
= TALLOC_P(frame
, struct sockaddr_storage
);
3086 return NT_STATUS_NO_MEMORY
;
3091 for (i
= 0; i
< num_addrs
; i
++) {
3092 cli
->dest_ss
= ss_arr
[i
];
3093 if (getenv("LIBSMB_PROG")) {
3094 cli
->fd
= sock_exec(getenv("LIBSMB_PROG"));
3096 uint16_t port
= cli
->port
;
3098 status
= open_smb_socket(&cli
->dest_ss
, &port
,
3099 cli
->timeout
, &cli
->fd
);
3100 if (NT_STATUS_IS_OK(status
)) {
3104 if (cli
->fd
== -1) {
3105 char addr
[INET6_ADDRSTRLEN
];
3106 print_sockaddr(addr
, sizeof(addr
), &ss_arr
[i
]);
3107 DEBUG(2,("Error connecting to %s (%s)\n",
3108 dest_ss
?addr
:host
,strerror(errno
)));
3110 /* Exit from loop on first connection. */
3115 if (cli
->fd
== -1) {
3117 return map_nt_error_from_unix(errno
);
3121 *dest_ss
= cli
->dest_ss
;
3124 set_socket_options(cli
->fd
, lp_socket_options());
3127 return NT_STATUS_OK
;
3131 establishes a connection to after the negprot.
3132 @param output_cli A fully initialised cli structure, non-null only on success
3133 @param dest_host The netbios name of the remote host
3134 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3135 @param port (optional) The destination port (0 for default)
3137 NTSTATUS
cli_start_connection(struct cli_state
**output_cli
,
3138 const char *my_name
,
3139 const char *dest_host
,
3140 struct sockaddr_storage
*dest_ss
, int port
,
3141 int signing_state
, int flags
)
3144 struct nmb_name calling
;
3145 struct nmb_name called
;
3146 struct cli_state
*cli
;
3147 struct sockaddr_storage ss
;
3150 my_name
= global_myname();
3152 if (!(cli
= cli_initialise_ex(signing_state
))) {
3153 return NT_STATUS_NO_MEMORY
;
3156 make_nmb_name(&calling
, my_name
, 0x0);
3157 make_nmb_name(&called
, dest_host
, 0x20);
3159 cli_set_port(cli
, port
);
3160 cli_set_timeout(cli
, 10000); /* 10 seconds. */
3170 DEBUG(3,("Connecting to host=%s\n", dest_host
));
3172 nt_status
= cli_connect(cli
, dest_host
, &ss
);
3173 if (!NT_STATUS_IS_OK(nt_status
)) {
3174 char addr
[INET6_ADDRSTRLEN
];
3175 print_sockaddr(addr
, sizeof(addr
), &ss
);
3176 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
3177 nmb_namestr(&called
), addr
, nt_errstr(nt_status
) ));
3182 if (!cli_session_request(cli
, &calling
, &called
)) {
3184 DEBUG(1,("session request to %s failed (%s)\n",
3185 called
.name
, cli_errstr(cli
)));
3186 if ((p
=strchr(called
.name
, '.')) && !is_ipaddress(called
.name
)) {
3190 if (strcmp(called
.name
, STAR_SMBSERVER
)) {
3191 make_nmb_name(&called
, STAR_SMBSERVER
, 0x20);
3194 return NT_STATUS_BAD_NETWORK_NAME
;
3197 if (flags
& CLI_FULL_CONNECTION_DONT_SPNEGO
)
3198 cli
->use_spnego
= False
;
3199 else if (flags
& CLI_FULL_CONNECTION_USE_KERBEROS
)
3200 cli
->use_kerberos
= True
;
3202 if ((flags
& CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS
) &&
3203 cli
->use_kerberos
) {
3204 cli
->fallback_after_kerberos
= true;
3206 if (flags
& CLI_FULL_CONNECTION_USE_CCACHE
) {
3207 cli
->use_ccache
= true;
3210 nt_status
= cli_negprot(cli
);
3211 if (!NT_STATUS_IS_OK(nt_status
)) {
3212 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status
)));
3218 return NT_STATUS_OK
;
3223 establishes a connection right up to doing tconX, password specified.
3224 @param output_cli A fully initialised cli structure, non-null only on success
3225 @param dest_host The netbios name of the remote host
3226 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3227 @param port (optional) The destination port (0 for default)
3228 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3229 @param service_type The 'type' of serivice.
3230 @param user Username, unix string
3231 @param domain User's domain
3232 @param password User's password, unencrypted unix string.
3235 NTSTATUS
cli_full_connection(struct cli_state
**output_cli
,
3236 const char *my_name
,
3237 const char *dest_host
,
3238 struct sockaddr_storage
*dest_ss
, int port
,
3239 const char *service
, const char *service_type
,
3240 const char *user
, const char *domain
,
3241 const char *password
, int flags
,
3245 struct cli_state
*cli
= NULL
;
3246 int pw_len
= password
? strlen(password
)+1 : 0;
3250 if (password
== NULL
) {
3254 nt_status
= cli_start_connection(&cli
, my_name
, dest_host
,
3255 dest_ss
, port
, signing_state
,
3258 if (!NT_STATUS_IS_OK(nt_status
)) {
3262 cli
->use_oplocks
= ((flags
& CLI_FULL_CONNECTION_OPLOCKS
) != 0);
3263 cli
->use_level_II_oplocks
=
3264 ((flags
& CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS
) != 0);
3266 nt_status
= cli_session_setup(cli
, user
, password
, pw_len
, password
,
3268 if (!NT_STATUS_IS_OK(nt_status
)) {
3270 if (!(flags
& CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK
)) {
3271 DEBUG(1,("failed session setup with %s\n",
3272 nt_errstr(nt_status
)));
3277 nt_status
= cli_session_setup(cli
, "", "", 0, "", 0, domain
);
3278 if (!NT_STATUS_IS_OK(nt_status
)) {
3279 DEBUG(1,("anonymous failed session setup with %s\n",
3280 nt_errstr(nt_status
)));
3287 nt_status
= cli_tcon_andx(cli
, service
, service_type
, password
,
3289 if (!NT_STATUS_IS_OK(nt_status
)) {
3290 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status
)));
3292 if (NT_STATUS_IS_OK(nt_status
)) {
3293 nt_status
= NT_STATUS_UNSUCCESSFUL
;
3299 nt_status
= cli_init_creds(cli
, user
, domain
, password
);
3300 if (!NT_STATUS_IS_OK(nt_status
)) {
3306 return NT_STATUS_OK
;
3309 /****************************************************************************
3310 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
3311 ****************************************************************************/
3313 bool attempt_netbios_session_request(struct cli_state
**ppcli
, const char *srchost
, const char *desthost
,
3314 struct sockaddr_storage
*pdest_ss
)
3316 struct nmb_name calling
, called
;
3318 make_nmb_name(&calling
, srchost
, 0x0);
3321 * If the called name is an IP address
3322 * then use *SMBSERVER immediately.
3325 if(is_ipaddress(desthost
)) {
3326 make_nmb_name(&called
, STAR_SMBSERVER
, 0x20);
3328 make_nmb_name(&called
, desthost
, 0x20);
3331 if (!cli_session_request(*ppcli
, &calling
, &called
)) {
3333 struct nmb_name smbservername
;
3335 make_nmb_name(&smbservername
, STAR_SMBSERVER
, 0x20);
3338 * If the name wasn't *SMBSERVER then
3339 * try with *SMBSERVER if the first name fails.
3342 if (nmb_name_equal(&called
, &smbservername
)) {
3345 * The name used was *SMBSERVER, don't bother with another name.
3348 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
3349 with error %s.\n", desthost
, cli_errstr(*ppcli
) ));
3354 cli_shutdown(*ppcli
);
3356 *ppcli
= cli_initialise();
3358 /* Out of memory... */
3362 status
= cli_connect(*ppcli
, desthost
, pdest_ss
);
3363 if (!NT_STATUS_IS_OK(status
) ||
3364 !cli_session_request(*ppcli
, &calling
, &smbservername
)) {
3365 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
3366 name *SMBSERVER with error %s\n", desthost
, cli_errstr(*ppcli
) ));
3374 /****************************************************************************
3375 Send an old style tcon.
3376 ****************************************************************************/
3377 NTSTATUS
cli_raw_tcon(struct cli_state
*cli
,
3378 const char *service
, const char *pass
, const char *dev
,
3379 uint16
*max_xmit
, uint16
*tid
)
3381 struct tevent_req
*req
;
3386 if (!lp_client_plaintext_auth() && (*pass
)) {
3387 DEBUG(1, ("Server requested plaintext password but 'client "
3388 "plaintext auth' is disabled\n"));
3389 return NT_STATUS_ACCESS_DENIED
;
3392 bytes
= talloc_array(talloc_tos(), uint8_t, 0);
3393 bytes
= smb_bytes_push_bytes(bytes
, 4, NULL
, 0);
3394 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
3395 service
, strlen(service
)+1, NULL
);
3396 bytes
= smb_bytes_push_bytes(bytes
, 4, NULL
, 0);
3397 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
3398 pass
, strlen(pass
)+1, NULL
);
3399 bytes
= smb_bytes_push_bytes(bytes
, 4, NULL
, 0);
3400 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
3401 dev
, strlen(dev
)+1, NULL
);
3403 status
= cli_smb(talloc_tos(), cli
, SMBtcon
, 0, 0, NULL
,
3404 talloc_get_size(bytes
), bytes
, &req
,
3405 2, NULL
, &ret_vwv
, NULL
, NULL
);
3406 if (!NT_STATUS_IS_OK(status
)) {
3410 *max_xmit
= SVAL(ret_vwv
+ 0, 0);
3411 *tid
= SVAL(ret_vwv
+ 1, 0);
3413 return NT_STATUS_OK
;
3416 /* Return a cli_state pointing at the IPC$ share for the given server */
3418 struct cli_state
*get_ipc_connect(char *server
,
3419 struct sockaddr_storage
*server_ss
,
3420 const struct user_auth_info
*user_info
)
3422 struct cli_state
*cli
;
3424 uint32_t flags
= CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK
;
3426 if (user_info
->use_kerberos
) {
3427 flags
|= CLI_FULL_CONNECTION_USE_KERBEROS
;
3430 nt_status
= cli_full_connection(&cli
, NULL
, server
, server_ss
, 0, "IPC$", "IPC",
3431 user_info
->username
? user_info
->username
: "",
3433 user_info
->password
? user_info
->password
: "",
3437 if (NT_STATUS_IS_OK(nt_status
)) {
3439 } else if (is_ipaddress(server
)) {
3440 /* windows 9* needs a correct NMB name for connections */
3441 fstring remote_name
;
3443 if (name_status_find("*", 0, 0, server_ss
, remote_name
)) {
3444 cli
= get_ipc_connect(remote_name
, server_ss
, user_info
);
3453 * Given the IP address of a master browser on the network, return its
3454 * workgroup and connect to it.
3456 * This function is provided to allow additional processing beyond what
3457 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3458 * browsers and obtain each master browsers' list of domains (in case the
3459 * first master browser is recently on the network and has not yet
3460 * synchronized with other master browsers and therefore does not yet have the
3461 * entire network browse list)
3464 struct cli_state
*get_ipc_connect_master_ip(TALLOC_CTX
*ctx
,
3465 struct sockaddr_storage
*mb_ip
,
3466 const struct user_auth_info
*user_info
,
3467 char **pp_workgroup_out
)
3469 char addr
[INET6_ADDRSTRLEN
];
3471 struct cli_state
*cli
;
3472 struct sockaddr_storage server_ss
;
3474 *pp_workgroup_out
= NULL
;
3476 print_sockaddr(addr
, sizeof(addr
), mb_ip
);
3477 DEBUG(99, ("Looking up name of master browser %s\n",
3481 * Do a name status query to find out the name of the master browser.
3482 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3483 * master browser will not respond to a wildcard query (or, at least,
3484 * an NT4 server acting as the domain master browser will not).
3486 * We might be able to use ONLY the query on MSBROWSE, but that's not
3487 * yet been tested with all Windows versions, so until it is, leave
3488 * the original wildcard query as the first choice and fall back to
3489 * MSBROWSE if the wildcard query fails.
3491 if (!name_status_find("*", 0, 0x1d, mb_ip
, name
) &&
3492 !name_status_find(MSBROWSE
, 1, 0x1d, mb_ip
, name
)) {
3494 DEBUG(99, ("Could not retrieve name status for %s\n",
3499 if (!find_master_ip(name
, &server_ss
)) {
3500 DEBUG(99, ("Could not find master ip for %s\n", name
));
3504 *pp_workgroup_out
= talloc_strdup(ctx
, name
);
3506 DEBUG(4, ("found master browser %s, %s\n", name
, addr
));
3508 print_sockaddr(addr
, sizeof(addr
), &server_ss
);
3509 cli
= get_ipc_connect(addr
, &server_ss
, user_info
);
3515 * Return the IP address and workgroup of a master browser on the network, and
3519 struct cli_state
*get_ipc_connect_master_ip_bcast(TALLOC_CTX
*ctx
,
3520 const struct user_auth_info
*user_info
,
3521 char **pp_workgroup_out
)
3523 struct sockaddr_storage
*ip_list
;
3524 struct cli_state
*cli
;
3528 *pp_workgroup_out
= NULL
;
3530 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3532 /* Go looking for workgroups by broadcasting on the local network */
3534 status
= name_resolve_bcast(MSBROWSE
, 1, talloc_tos(),
3536 if (!NT_STATUS_IS_OK(status
)) {
3537 DEBUG(99, ("No master browsers responded: %s\n",
3538 nt_errstr(status
)));
3542 for (i
= 0; i
< count
; i
++) {
3543 char addr
[INET6_ADDRSTRLEN
];
3544 print_sockaddr(addr
, sizeof(addr
), &ip_list
[i
]);
3545 DEBUG(99, ("Found master browser %s\n", addr
));
3547 cli
= get_ipc_connect_master_ip(ctx
, &ip_list
[i
],
3548 user_info
, pp_workgroup_out
);