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(NULL
, 16);
98 data_blob_clear(&cli
->user_session_key
);
99 memcpy(cli
->user_session_key
.data
, session_key
.data
, MIN(session_key
.length
, 16));
102 /****************************************************************************
103 Do an old lanman2 style session setup.
104 ****************************************************************************/
106 struct cli_session_setup_lanman2_state
{
107 struct cli_state
*cli
;
112 static void cli_session_setup_lanman2_done(struct tevent_req
*subreq
);
114 static struct tevent_req
*cli_session_setup_lanman2_send(
115 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
116 struct cli_state
*cli
, const char *user
,
117 const char *pass
, size_t passlen
,
118 const char *workgroup
)
120 struct tevent_req
*req
, *subreq
;
121 struct cli_session_setup_lanman2_state
*state
;
122 DATA_BLOB lm_response
= data_blob_null
;
127 req
= tevent_req_create(mem_ctx
, &state
,
128 struct cli_session_setup_lanman2_state
);
137 * LANMAN servers predate NT status codes and Unicode and
138 * ignore those smb flags so we must disable the corresponding
139 * default capabilities that would otherwise cause the Unicode
140 * and NT Status flags to be set (and even returned by the
144 cli
->capabilities
&= ~(CAP_UNICODE
| CAP_STATUS32
);
147 * if in share level security then don't send a password now
149 if (!(cli
->sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
)) {
154 && (cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
)
157 * Encrypted mode needed, and non encrypted password
160 lm_response
= data_blob(NULL
, 24);
161 if (tevent_req_nomem(lm_response
.data
, req
)) {
162 return tevent_req_post(req
, ev
);
165 if (!SMBencrypt(pass
, cli
->secblob
.data
,
166 (uint8_t *)lm_response
.data
)) {
167 DEBUG(1, ("Password is > 14 chars in length, and is "
168 "therefore incompatible with Lanman "
169 "authentication\n"));
170 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
171 return tevent_req_post(req
, ev
);
173 } else if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
)
176 * Encrypted mode needed, and encrypted password
179 lm_response
= data_blob(pass
, passlen
);
180 if (tevent_req_nomem(lm_response
.data
, req
)) {
181 return tevent_req_post(req
, ev
);
183 } else if (passlen
> 0) {
185 size_t converted_size
;
187 * Plaintext mode needed, assume plaintext supplied.
189 buf
= talloc_array(talloc_tos(), uint8_t, 0);
190 buf
= smb_bytes_push_str(buf
, cli_ucs2(cli
), pass
, passlen
+1,
192 if (tevent_req_nomem(buf
, req
)) {
193 return tevent_req_post(req
, ev
);
195 lm_response
= data_blob(pass
, passlen
);
197 if (tevent_req_nomem(lm_response
.data
, req
)) {
198 return tevent_req_post(req
, ev
);
202 SCVAL(vwv
+0, 0, 0xff);
205 SSVAL(vwv
+2, 0, CLI_BUFFER_SIZE
);
208 SIVAL(vwv
+5, 0, cli
->sesskey
);
209 SSVAL(vwv
+7, 0, lm_response
.length
);
211 bytes
= talloc_array(state
, uint8_t, lm_response
.length
);
212 if (tevent_req_nomem(bytes
, req
)) {
213 return tevent_req_post(req
, ev
);
215 if (lm_response
.length
!= 0) {
216 memcpy(bytes
, lm_response
.data
, lm_response
.length
);
218 data_blob_free(&lm_response
);
220 tmp
= talloc_strdup_upper(talloc_tos(), user
);
221 if (tevent_req_nomem(tmp
, req
)) {
222 return tevent_req_post(req
, ev
);
224 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), tmp
, strlen(tmp
)+1,
228 tmp
= talloc_strdup_upper(talloc_tos(), workgroup
);
229 if (tevent_req_nomem(tmp
, req
)) {
230 return tevent_req_post(req
, ev
);
232 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), tmp
, strlen(tmp
)+1,
234 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "Unix", 5, NULL
);
235 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "Samba", 6, NULL
);
237 if (tevent_req_nomem(bytes
, req
)) {
238 return tevent_req_post(req
, ev
);
241 subreq
= cli_smb_send(state
, ev
, cli
, SMBsesssetupX
, 0, 10, vwv
,
242 talloc_get_size(bytes
), bytes
);
243 if (tevent_req_nomem(subreq
, req
)) {
244 return tevent_req_post(req
, ev
);
246 tevent_req_set_callback(subreq
, cli_session_setup_lanman2_done
, req
);
250 static void cli_session_setup_lanman2_done(struct tevent_req
*subreq
)
252 struct tevent_req
*req
= tevent_req_callback_data(
253 subreq
, struct tevent_req
);
254 struct cli_session_setup_lanman2_state
*state
= tevent_req_data(
255 req
, struct cli_session_setup_lanman2_state
);
256 struct cli_state
*cli
= state
->cli
;
267 status
= cli_smb_recv(subreq
, state
, &in
, 3, &wct
, &vwv
,
270 if (!NT_STATUS_IS_OK(status
)) {
271 tevent_req_nterror(req
, status
);
278 cli
->vuid
= SVAL(inbuf
, smb_uid
);
279 cli
->is_guestlogin
= ((SVAL(vwv
+2, 0) & 1) != 0);
281 status
= smb_bytes_talloc_string(cli
,
288 if (!NT_STATUS_IS_OK(status
)) {
289 tevent_req_nterror(req
, status
);
294 status
= smb_bytes_talloc_string(cli
,
301 if (!NT_STATUS_IS_OK(status
)) {
302 tevent_req_nterror(req
, status
);
307 status
= smb_bytes_talloc_string(cli
,
314 if (!NT_STATUS_IS_OK(status
)) {
315 tevent_req_nterror(req
, status
);
320 if (strstr(cli
->server_type
, "Samba")) {
321 cli
->is_samba
= True
;
323 status
= cli_set_username(cli
, state
->user
);
324 if (tevent_req_nterror(req
, status
)) {
327 tevent_req_done(req
);
330 static NTSTATUS
cli_session_setup_lanman2_recv(struct tevent_req
*req
)
332 return tevent_req_simple_recv_ntstatus(req
);
335 static NTSTATUS
cli_session_setup_lanman2(struct cli_state
*cli
, const char *user
,
336 const char *pass
, size_t passlen
,
337 const char *workgroup
)
339 TALLOC_CTX
*frame
= talloc_stackframe();
340 struct event_context
*ev
;
341 struct tevent_req
*req
;
342 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
344 if (cli_has_async_calls(cli
)) {
346 * Can't use sync call while an async call is in flight
348 status
= NT_STATUS_INVALID_PARAMETER
;
351 ev
= event_context_init(frame
);
355 req
= cli_session_setup_lanman2_send(frame
, ev
, cli
, user
, pass
, passlen
,
360 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
363 status
= cli_session_setup_lanman2_recv(req
);
369 /****************************************************************************
370 Work out suitable capabilities to offer the server.
371 ****************************************************************************/
373 static uint32
cli_session_setup_capabilities(struct cli_state
*cli
)
375 uint32 capabilities
= CAP_NT_SMBS
;
377 if (!cli
->force_dos_errors
)
378 capabilities
|= CAP_STATUS32
;
380 if (cli
->use_level_II_oplocks
)
381 capabilities
|= CAP_LEVEL_II_OPLOCKS
;
383 capabilities
|= (cli
->capabilities
& (CAP_UNICODE
|CAP_LARGE_FILES
|CAP_LARGE_READX
|CAP_LARGE_WRITEX
|CAP_DFS
));
387 /****************************************************************************
388 Do a NT1 guest session setup.
389 ****************************************************************************/
391 struct cli_session_setup_guest_state
{
392 struct cli_state
*cli
;
397 static void cli_session_setup_guest_done(struct tevent_req
*subreq
);
399 struct tevent_req
*cli_session_setup_guest_create(TALLOC_CTX
*mem_ctx
,
400 struct event_context
*ev
,
401 struct cli_state
*cli
,
402 struct tevent_req
**psmbreq
)
404 struct tevent_req
*req
, *subreq
;
405 struct cli_session_setup_guest_state
*state
;
409 req
= tevent_req_create(mem_ctx
, &state
,
410 struct cli_session_setup_guest_state
);
417 SCVAL(vwv
+0, 0, 0xFF);
420 SSVAL(vwv
+2, 0, CLI_BUFFER_SIZE
);
422 SSVAL(vwv
+4, 0, cli
->pid
);
423 SIVAL(vwv
+5, 0, cli
->sesskey
);
428 SIVAL(vwv
+11, 0, cli_session_setup_capabilities(cli
));
430 bytes
= talloc_array(state
, uint8_t, 0);
432 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "", 1, /* username */
434 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "", 1, /* workgroup */
436 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "Unix", 5, NULL
);
437 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "Samba", 6, NULL
);
444 state
->bytes
.iov_base
= (void *)bytes
;
445 state
->bytes
.iov_len
= talloc_get_size(bytes
);
447 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBsesssetupX
, 0, 13, vwv
,
449 if (subreq
== NULL
) {
453 tevent_req_set_callback(subreq
, cli_session_setup_guest_done
, req
);
458 struct tevent_req
*cli_session_setup_guest_send(TALLOC_CTX
*mem_ctx
,
459 struct event_context
*ev
,
460 struct cli_state
*cli
)
462 struct tevent_req
*req
, *subreq
;
465 req
= cli_session_setup_guest_create(mem_ctx
, ev
, cli
, &subreq
);
470 status
= cli_smb_req_send(subreq
);
471 if (NT_STATUS_IS_OK(status
)) {
472 tevent_req_nterror(req
, status
);
473 return tevent_req_post(req
, ev
);
478 static void cli_session_setup_guest_done(struct tevent_req
*subreq
)
480 struct tevent_req
*req
= tevent_req_callback_data(
481 subreq
, struct tevent_req
);
482 struct cli_session_setup_guest_state
*state
= tevent_req_data(
483 req
, struct cli_session_setup_guest_state
);
484 struct cli_state
*cli
= state
->cli
;
495 status
= cli_smb_recv(subreq
, state
, &in
, 3, &wct
, &vwv
,
498 if (!NT_STATUS_IS_OK(status
)) {
499 tevent_req_nterror(req
, status
);
506 cli
->vuid
= SVAL(inbuf
, smb_uid
);
507 cli
->is_guestlogin
= ((SVAL(vwv
+2, 0) & 1) != 0);
509 status
= smb_bytes_talloc_string(cli
,
516 if (!NT_STATUS_IS_OK(status
)) {
517 tevent_req_nterror(req
, status
);
522 status
= smb_bytes_talloc_string(cli
,
529 if (!NT_STATUS_IS_OK(status
)) {
530 tevent_req_nterror(req
, status
);
535 status
= smb_bytes_talloc_string(cli
,
542 if (!NT_STATUS_IS_OK(status
)) {
543 tevent_req_nterror(req
, status
);
548 if (strstr(cli
->server_type
, "Samba")) {
549 cli
->is_samba
= True
;
552 status
= cli_set_username(cli
, "");
553 if (!NT_STATUS_IS_OK(status
)) {
554 tevent_req_nterror(req
, status
);
557 tevent_req_done(req
);
560 NTSTATUS
cli_session_setup_guest_recv(struct tevent_req
*req
)
562 return tevent_req_simple_recv_ntstatus(req
);
565 static NTSTATUS
cli_session_setup_guest(struct cli_state
*cli
)
567 TALLOC_CTX
*frame
= talloc_stackframe();
568 struct event_context
*ev
;
569 struct tevent_req
*req
;
570 NTSTATUS status
= NT_STATUS_OK
;
572 if (cli_has_async_calls(cli
)) {
574 * Can't use sync call while an async call is in flight
576 status
= NT_STATUS_INVALID_PARAMETER
;
580 ev
= event_context_init(frame
);
582 status
= NT_STATUS_NO_MEMORY
;
586 req
= cli_session_setup_guest_send(frame
, ev
, cli
);
588 status
= NT_STATUS_NO_MEMORY
;
592 if (!tevent_req_poll(req
, ev
)) {
593 status
= map_nt_error_from_unix(errno
);
597 status
= cli_session_setup_guest_recv(req
);
603 /****************************************************************************
604 Do a NT1 plaintext session setup.
605 ****************************************************************************/
607 struct cli_session_setup_plain_state
{
608 struct cli_state
*cli
;
613 static void cli_session_setup_plain_done(struct tevent_req
*subreq
);
615 static struct tevent_req
*cli_session_setup_plain_send(
616 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
617 struct cli_state
*cli
,
618 const char *user
, const char *pass
, const char *workgroup
)
620 struct tevent_req
*req
, *subreq
;
621 struct cli_session_setup_plain_state
*state
;
627 req
= tevent_req_create(mem_ctx
, &state
,
628 struct cli_session_setup_plain_state
);
636 SCVAL(vwv
+0, 0, 0xff);
639 SSVAL(vwv
+2, 0, CLI_BUFFER_SIZE
);
641 SSVAL(vwv
+4, 0, cli
->pid
);
642 SIVAL(vwv
+5, 0, cli
->sesskey
);
647 SIVAL(vwv
+11, 0, cli_session_setup_capabilities(cli
));
649 bytes
= talloc_array(state
, uint8_t, 0);
650 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), pass
, strlen(pass
)+1,
652 if (tevent_req_nomem(bytes
, req
)) {
653 return tevent_req_post(req
, ev
);
655 SSVAL(vwv
+ (cli_ucs2(cli
) ? 8 : 7), 0, passlen
);
657 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
658 user
, strlen(user
)+1, NULL
);
659 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
660 workgroup
, strlen(workgroup
)+1, NULL
);
661 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
664 version
= talloc_asprintf(talloc_tos(), "Samba %s",
665 samba_version_string());
666 if (tevent_req_nomem(version
, req
)){
667 return tevent_req_post(req
, ev
);
669 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
670 version
, strlen(version
)+1, NULL
);
671 TALLOC_FREE(version
);
673 if (tevent_req_nomem(bytes
, req
)) {
674 return tevent_req_post(req
, ev
);
677 subreq
= cli_smb_send(state
, ev
, cli
, SMBsesssetupX
, 0, 13, vwv
,
678 talloc_get_size(bytes
), bytes
);
679 if (tevent_req_nomem(subreq
, req
)) {
680 return tevent_req_post(req
, ev
);
682 tevent_req_set_callback(subreq
, cli_session_setup_plain_done
, req
);
686 static void cli_session_setup_plain_done(struct tevent_req
*subreq
)
688 struct tevent_req
*req
= tevent_req_callback_data(
689 subreq
, struct tevent_req
);
690 struct cli_session_setup_plain_state
*state
= tevent_req_data(
691 req
, struct cli_session_setup_plain_state
);
692 struct cli_state
*cli
= state
->cli
;
703 status
= cli_smb_recv(subreq
, state
, &in
, 3, &wct
, &vwv
,
706 if (tevent_req_nterror(req
, status
)) {
713 cli
->vuid
= SVAL(inbuf
, smb_uid
);
714 cli
->is_guestlogin
= ((SVAL(vwv
+2, 0) & 1) != 0);
716 status
= smb_bytes_talloc_string(cli
,
723 if (!NT_STATUS_IS_OK(status
)) {
724 tevent_req_nterror(req
, status
);
729 status
= smb_bytes_talloc_string(cli
,
736 if (!NT_STATUS_IS_OK(status
)) {
737 tevent_req_nterror(req
, status
);
742 status
= smb_bytes_talloc_string(cli
,
749 if (!NT_STATUS_IS_OK(status
)) {
750 tevent_req_nterror(req
, status
);
755 status
= cli_set_username(cli
, state
->user
);
756 if (tevent_req_nterror(req
, status
)) {
759 if (strstr(cli
->server_type
, "Samba")) {
760 cli
->is_samba
= True
;
762 tevent_req_done(req
);
765 static NTSTATUS
cli_session_setup_plain_recv(struct tevent_req
*req
)
767 return tevent_req_simple_recv_ntstatus(req
);
770 static NTSTATUS
cli_session_setup_plain(struct cli_state
*cli
,
771 const char *user
, const char *pass
,
772 const char *workgroup
)
774 TALLOC_CTX
*frame
= talloc_stackframe();
775 struct event_context
*ev
;
776 struct tevent_req
*req
;
777 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
779 if (cli_has_async_calls(cli
)) {
781 * Can't use sync call while an async call is in flight
783 status
= NT_STATUS_INVALID_PARAMETER
;
786 ev
= event_context_init(frame
);
790 req
= cli_session_setup_plain_send(frame
, ev
, cli
, user
, pass
,
795 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
798 status
= cli_session_setup_plain_recv(req
);
804 /****************************************************************************
805 do a NT1 NTLM/LM encrypted session setup - for when extended security
807 @param cli client state to create do session setup on
809 @param pass *either* cleartext password (passlen !=24) or LM response.
810 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
811 @param workgroup The user's domain.
812 ****************************************************************************/
814 struct cli_session_setup_nt1_state
{
815 struct cli_state
*cli
;
818 DATA_BLOB session_key
;
822 static void cli_session_setup_nt1_done(struct tevent_req
*subreq
);
824 static struct tevent_req
*cli_session_setup_nt1_send(
825 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
826 struct cli_state
*cli
, const char *user
,
827 const char *pass
, size_t passlen
,
828 const char *ntpass
, size_t ntpasslen
,
829 const char *workgroup
)
831 struct tevent_req
*req
, *subreq
;
832 struct cli_session_setup_nt1_state
*state
;
833 DATA_BLOB lm_response
= data_blob_null
;
834 DATA_BLOB nt_response
= data_blob_null
;
835 DATA_BLOB session_key
= data_blob_null
;
838 char *workgroup_upper
;
840 req
= tevent_req_create(mem_ctx
, &state
,
841 struct cli_session_setup_nt1_state
);
850 /* do nothing - guest login */
851 } else if (passlen
!= 24) {
852 if (lp_client_ntlmv2_auth()) {
853 DATA_BLOB server_chal
;
854 DATA_BLOB names_blob
;
856 server_chal
= data_blob(cli
->secblob
.data
,
857 MIN(cli
->secblob
.length
, 8));
858 if (tevent_req_nomem(server_chal
.data
, req
)) {
859 return tevent_req_post(req
, ev
);
863 * note that the 'workgroup' here is a best
864 * guess - we don't know the server's domain
865 * at this point. The 'server name' is also
868 names_blob
= NTLMv2_generate_names_blob(
869 NULL
, cli
->called
.name
, workgroup
);
871 if (tevent_req_nomem(names_blob
.data
, req
)) {
872 return tevent_req_post(req
, ev
);
875 if (!SMBNTLMv2encrypt(NULL
, user
, workgroup
, pass
,
876 &server_chal
, &names_blob
,
877 &lm_response
, &nt_response
,
878 NULL
, &session_key
)) {
879 data_blob_free(&names_blob
);
880 data_blob_free(&server_chal
);
882 req
, NT_STATUS_ACCESS_DENIED
);
883 return tevent_req_post(req
, ev
);
885 data_blob_free(&names_blob
);
886 data_blob_free(&server_chal
);
890 E_md4hash(pass
, nt_hash
);
893 nt_response
= data_blob_null
;
895 nt_response
= data_blob(NULL
, 24);
896 if (tevent_req_nomem(nt_response
.data
, req
)) {
897 return tevent_req_post(req
, ev
);
900 SMBNTencrypt(pass
, cli
->secblob
.data
,
903 /* non encrypted password supplied. Ignore ntpass. */
904 if (lp_client_lanman_auth()) {
906 lm_response
= data_blob(NULL
, 24);
907 if (tevent_req_nomem(lm_response
.data
, req
)) {
908 return tevent_req_post(req
, ev
);
911 if (!SMBencrypt(pass
,cli
->secblob
.data
,
914 * Oops, the LM response is
915 * invalid, just put the NT
916 * response there instead
918 data_blob_free(&lm_response
);
919 lm_response
= data_blob(
925 * LM disabled, place NT# in LM field
928 lm_response
= data_blob(
929 nt_response
.data
, nt_response
.length
);
932 if (tevent_req_nomem(lm_response
.data
, req
)) {
933 return tevent_req_post(req
, ev
);
936 session_key
= data_blob(NULL
, 16);
937 if (tevent_req_nomem(session_key
.data
, req
)) {
938 return tevent_req_post(req
, ev
);
941 E_deshash(pass
, session_key
.data
);
942 memset(&session_key
.data
[8], '\0', 8);
944 SMBsesskeygen_ntv1(nt_hash
, session_key
.data
);
947 cli_temp_set_signing(cli
);
949 /* pre-encrypted password supplied. Only used for
950 security=server, can't do
951 signing because we don't have original key */
953 lm_response
= data_blob(pass
, passlen
);
954 if (tevent_req_nomem(lm_response
.data
, req
)) {
955 return tevent_req_post(req
, ev
);
958 nt_response
= data_blob(ntpass
, ntpasslen
);
959 if (tevent_req_nomem(nt_response
.data
, req
)) {
960 return tevent_req_post(req
, ev
);
965 state
->response
= data_blob_talloc(
966 state
, lm_response
.data
, lm_response
.length
);
968 state
->response
= data_blob_talloc(
969 state
, nt_response
.data
, nt_response
.length
);
971 if (tevent_req_nomem(state
->response
.data
, req
)) {
972 return tevent_req_post(req
, ev
);
975 if (session_key
.data
) {
976 state
->session_key
= data_blob_talloc(
977 state
, session_key
.data
, session_key
.length
);
978 if (tevent_req_nomem(state
->session_key
.data
, req
)) {
979 return tevent_req_post(req
, ev
);
982 data_blob_free(&session_key
);
984 SCVAL(vwv
+0, 0, 0xff);
987 SSVAL(vwv
+2, 0, CLI_BUFFER_SIZE
);
989 SSVAL(vwv
+4, 0, cli
->pid
);
990 SIVAL(vwv
+5, 0, cli
->sesskey
);
991 SSVAL(vwv
+7, 0, lm_response
.length
);
992 SSVAL(vwv
+8, 0, nt_response
.length
);
995 SIVAL(vwv
+11, 0, cli_session_setup_capabilities(cli
));
997 bytes
= talloc_array(state
, uint8_t,
998 lm_response
.length
+ nt_response
.length
);
999 if (tevent_req_nomem(bytes
, req
)) {
1000 return tevent_req_post(req
, ev
);
1002 if (lm_response
.length
!= 0) {
1003 memcpy(bytes
, lm_response
.data
, lm_response
.length
);
1005 if (nt_response
.length
!= 0) {
1006 memcpy(bytes
+ lm_response
.length
,
1007 nt_response
.data
, nt_response
.length
);
1009 data_blob_free(&lm_response
);
1010 data_blob_free(&nt_response
);
1012 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
1013 user
, strlen(user
)+1, NULL
);
1016 * Upper case here might help some NTLMv2 implementations
1018 workgroup_upper
= talloc_strdup_upper(talloc_tos(), workgroup
);
1019 if (tevent_req_nomem(workgroup_upper
, req
)) {
1020 return tevent_req_post(req
, ev
);
1022 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
1023 workgroup_upper
, strlen(workgroup_upper
)+1,
1025 TALLOC_FREE(workgroup_upper
);
1027 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "Unix", 5, NULL
);
1028 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "Samba", 6, NULL
);
1029 if (tevent_req_nomem(bytes
, req
)) {
1030 return tevent_req_post(req
, ev
);
1033 subreq
= cli_smb_send(state
, ev
, cli
, SMBsesssetupX
, 0, 13, vwv
,
1034 talloc_get_size(bytes
), bytes
);
1035 if (tevent_req_nomem(subreq
, req
)) {
1036 return tevent_req_post(req
, ev
);
1038 tevent_req_set_callback(subreq
, cli_session_setup_nt1_done
, req
);
1042 static void cli_session_setup_nt1_done(struct tevent_req
*subreq
)
1044 struct tevent_req
*req
= tevent_req_callback_data(
1045 subreq
, struct tevent_req
);
1046 struct cli_session_setup_nt1_state
*state
= tevent_req_data(
1047 req
, struct cli_session_setup_nt1_state
);
1048 struct cli_state
*cli
= state
->cli
;
1059 status
= cli_smb_recv(subreq
, state
, &in
, 3, &wct
, &vwv
,
1060 &num_bytes
, &bytes
);
1061 TALLOC_FREE(subreq
);
1062 if (!NT_STATUS_IS_OK(status
)) {
1063 tevent_req_nterror(req
, status
);
1070 cli
->vuid
= SVAL(inbuf
, smb_uid
);
1071 cli
->is_guestlogin
= ((SVAL(vwv
+2, 0) & 1) != 0);
1073 status
= smb_bytes_talloc_string(cli
,
1079 if (!NT_STATUS_IS_OK(status
)) {
1080 tevent_req_nterror(req
, status
);
1085 status
= smb_bytes_talloc_string(cli
,
1091 if (!NT_STATUS_IS_OK(status
)) {
1092 tevent_req_nterror(req
, status
);
1097 status
= smb_bytes_talloc_string(cli
,
1099 &cli
->server_domain
,
1103 if (!NT_STATUS_IS_OK(status
)) {
1104 tevent_req_nterror(req
, status
);
1109 if (strstr(cli
->server_type
, "Samba")) {
1110 cli
->is_samba
= True
;
1113 status
= cli_set_username(cli
, state
->user
);
1114 if (tevent_req_nterror(req
, status
)) {
1117 if (cli_simple_set_signing(cli
, state
->session_key
, state
->response
)
1118 && !cli_check_sign_mac(cli
, (char *)in
, 1)) {
1119 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1122 if (state
->session_key
.data
) {
1123 /* Have plaintext orginal */
1124 cli_set_session_key(cli
, state
->session_key
);
1126 tevent_req_done(req
);
1129 static NTSTATUS
cli_session_setup_nt1_recv(struct tevent_req
*req
)
1131 return tevent_req_simple_recv_ntstatus(req
);
1134 static NTSTATUS
cli_session_setup_nt1(struct cli_state
*cli
, const char *user
,
1135 const char *pass
, size_t passlen
,
1136 const char *ntpass
, size_t ntpasslen
,
1137 const char *workgroup
)
1139 TALLOC_CTX
*frame
= talloc_stackframe();
1140 struct event_context
*ev
;
1141 struct tevent_req
*req
;
1142 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1144 if (cli_has_async_calls(cli
)) {
1146 * Can't use sync call while an async call is in flight
1148 status
= NT_STATUS_INVALID_PARAMETER
;
1151 ev
= event_context_init(frame
);
1155 req
= cli_session_setup_nt1_send(frame
, ev
, cli
, user
, pass
, passlen
,
1156 ntpass
, ntpasslen
, workgroup
);
1160 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1163 status
= cli_session_setup_nt1_recv(req
);
1169 /* The following is calculated from :
1171 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
1172 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1176 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1178 struct cli_sesssetup_blob_state
{
1179 struct tevent_context
*ev
;
1180 struct cli_state
*cli
;
1182 uint16_t max_blob_size
;
1191 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state
*state
,
1192 struct tevent_req
**psubreq
);
1193 static void cli_sesssetup_blob_done(struct tevent_req
*subreq
);
1195 static struct tevent_req
*cli_sesssetup_blob_send(TALLOC_CTX
*mem_ctx
,
1196 struct tevent_context
*ev
,
1197 struct cli_state
*cli
,
1200 struct tevent_req
*req
, *subreq
;
1201 struct cli_sesssetup_blob_state
*state
;
1203 req
= tevent_req_create(mem_ctx
, &state
,
1204 struct cli_sesssetup_blob_state
);
1212 if (cli
->max_xmit
< BASE_SESSSETUP_BLOB_PACKET_SIZE
+ 1) {
1213 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1214 "(was %u, need minimum %u)\n",
1215 (unsigned int)cli
->max_xmit
,
1216 BASE_SESSSETUP_BLOB_PACKET_SIZE
));
1217 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1218 return tevent_req_post(req
, ev
);
1220 state
->max_blob_size
=
1221 MIN(cli
->max_xmit
- BASE_SESSSETUP_BLOB_PACKET_SIZE
, 0xFFFF);
1223 if (!cli_sesssetup_blob_next(state
, &subreq
)) {
1224 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
1225 return tevent_req_post(req
, ev
);
1227 tevent_req_set_callback(subreq
, cli_sesssetup_blob_done
, req
);
1231 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state
*state
,
1232 struct tevent_req
**psubreq
)
1234 struct tevent_req
*subreq
;
1237 SCVAL(state
->vwv
+0, 0, 0xFF);
1238 SCVAL(state
->vwv
+0, 1, 0);
1239 SSVAL(state
->vwv
+1, 0, 0);
1240 SSVAL(state
->vwv
+2, 0, CLI_BUFFER_SIZE
);
1241 SSVAL(state
->vwv
+3, 0, 2);
1242 SSVAL(state
->vwv
+4, 0, 1);
1243 SIVAL(state
->vwv
+5, 0, 0);
1245 thistime
= MIN(state
->blob
.length
, state
->max_blob_size
);
1246 SSVAL(state
->vwv
+7, 0, thistime
);
1248 SSVAL(state
->vwv
+8, 0, 0);
1249 SSVAL(state
->vwv
+9, 0, 0);
1250 SIVAL(state
->vwv
+10, 0,
1251 cli_session_setup_capabilities(state
->cli
)
1252 | CAP_EXTENDED_SECURITY
);
1254 state
->buf
= (uint8_t *)talloc_memdup(state
, state
->blob
.data
,
1256 if (state
->buf
== NULL
) {
1259 state
->blob
.data
+= thistime
;
1260 state
->blob
.length
-= thistime
;
1262 state
->buf
= smb_bytes_push_str(state
->buf
, cli_ucs2(state
->cli
),
1264 state
->buf
= smb_bytes_push_str(state
->buf
, cli_ucs2(state
->cli
),
1266 if (state
->buf
== NULL
) {
1269 subreq
= cli_smb_send(state
, state
->ev
, state
->cli
, SMBsesssetupX
, 0,
1271 talloc_get_size(state
->buf
), state
->buf
);
1272 if (subreq
== NULL
) {
1279 static void cli_sesssetup_blob_done(struct tevent_req
*subreq
)
1281 struct tevent_req
*req
= tevent_req_callback_data(
1282 subreq
, struct tevent_req
);
1283 struct cli_sesssetup_blob_state
*state
= tevent_req_data(
1284 req
, struct cli_sesssetup_blob_state
);
1285 struct cli_state
*cli
= state
->cli
;
1292 uint16_t blob_length
;
1296 status
= cli_smb_recv(subreq
, state
, &inbuf
, 4, &wct
, &vwv
,
1297 &num_bytes
, &bytes
);
1298 TALLOC_FREE(subreq
);
1299 if (!NT_STATUS_IS_OK(status
)
1300 && !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1301 tevent_req_nterror(req
, status
);
1305 state
->status
= status
;
1306 TALLOC_FREE(state
->buf
);
1308 state
->inbuf
= (char *)inbuf
;
1309 cli
->vuid
= SVAL(state
->inbuf
, smb_uid
);
1310 cli
->is_guestlogin
= ((SVAL(vwv
+2, 0) & 1) != 0);
1312 blob_length
= SVAL(vwv
+3, 0);
1313 if (blob_length
> num_bytes
) {
1314 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
1317 state
->ret_blob
= data_blob_const(bytes
, blob_length
);
1319 p
= bytes
+ blob_length
;
1321 status
= smb_bytes_talloc_string(cli
,
1328 if (!NT_STATUS_IS_OK(status
)) {
1329 tevent_req_nterror(req
, status
);
1334 status
= smb_bytes_talloc_string(cli
,
1341 if (!NT_STATUS_IS_OK(status
)) {
1342 tevent_req_nterror(req
, status
);
1347 status
= smb_bytes_talloc_string(cli
,
1349 &cli
->server_domain
,
1354 if (!NT_STATUS_IS_OK(status
)) {
1355 tevent_req_nterror(req
, status
);
1360 if (strstr(cli
->server_type
, "Samba")) {
1361 cli
->is_samba
= True
;
1364 if (state
->blob
.length
!= 0) {
1368 if (!cli_sesssetup_blob_next(state
, &subreq
)) {
1369 tevent_req_nomem(NULL
, req
);
1372 tevent_req_set_callback(subreq
, cli_sesssetup_blob_done
, req
);
1375 tevent_req_done(req
);
1378 static NTSTATUS
cli_sesssetup_blob_recv(struct tevent_req
*req
,
1379 TALLOC_CTX
*mem_ctx
,
1383 struct cli_sesssetup_blob_state
*state
= tevent_req_data(
1384 req
, struct cli_sesssetup_blob_state
);
1388 if (tevent_req_is_nterror(req
, &status
)) {
1389 state
->cli
->vuid
= 0;
1393 inbuf
= talloc_move(mem_ctx
, &state
->inbuf
);
1394 if (pblob
!= NULL
) {
1395 *pblob
= state
->ret_blob
;
1397 if (pinbuf
!= NULL
) {
1400 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1401 return state
->status
;
1406 /****************************************************************************
1407 Use in-memory credentials cache
1408 ****************************************************************************/
1410 static void use_in_memory_ccache(void) {
1411 setenv(KRB5_ENV_CCNAME
, "MEMORY:cliconnect", 1);
1414 /****************************************************************************
1415 Do a spnego/kerberos encrypted session setup.
1416 ****************************************************************************/
1418 struct cli_session_setup_kerberos_state
{
1419 struct cli_state
*cli
;
1420 DATA_BLOB negTokenTarg
;
1421 DATA_BLOB session_key_krb5
;
1422 ADS_STATUS ads_status
;
1425 static void cli_session_setup_kerberos_done(struct tevent_req
*subreq
);
1427 static struct tevent_req
*cli_session_setup_kerberos_send(
1428 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
, struct cli_state
*cli
,
1429 const char *principal
, const char *workgroup
)
1431 struct tevent_req
*req
, *subreq
;
1432 struct cli_session_setup_kerberos_state
*state
;
1435 DEBUG(2,("Doing kerberos session setup\n"));
1437 req
= tevent_req_create(mem_ctx
, &state
,
1438 struct cli_session_setup_kerberos_state
);
1443 state
->ads_status
= ADS_SUCCESS
;
1445 cli_temp_set_signing(cli
);
1448 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1449 * we have to acquire a ticket. To be fixed later :-)
1451 rc
= spnego_gen_krb5_negTokenInit(state
, principal
, 0, &state
->negTokenTarg
,
1452 &state
->session_key_krb5
, 0, NULL
);
1454 DEBUG(1, ("cli_session_setup_kerberos: "
1455 "spnego_gen_krb5_negTokenInit failed: %s\n",
1456 error_message(rc
)));
1457 state
->ads_status
= ADS_ERROR_KRB5(rc
);
1458 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
1459 return tevent_req_post(req
, ev
);
1463 file_save("negTokenTarg.dat", state
->negTokenTarg
.data
,
1464 state
->negTokenTarg
.length
);
1467 subreq
= cli_sesssetup_blob_send(state
, ev
, cli
, state
->negTokenTarg
);
1468 if (tevent_req_nomem(subreq
, req
)) {
1469 return tevent_req_post(req
, ev
);
1471 tevent_req_set_callback(subreq
, cli_session_setup_kerberos_done
, req
);
1475 static void cli_session_setup_kerberos_done(struct tevent_req
*subreq
)
1477 struct tevent_req
*req
= tevent_req_callback_data(
1478 subreq
, struct tevent_req
);
1479 struct cli_session_setup_kerberos_state
*state
= tevent_req_data(
1480 req
, struct cli_session_setup_kerberos_state
);
1484 status
= cli_sesssetup_blob_recv(subreq
, talloc_tos(), NULL
, &inbuf
);
1485 if (!NT_STATUS_IS_OK(status
)) {
1486 TALLOC_FREE(subreq
);
1487 tevent_req_nterror(req
, status
);
1491 cli_set_session_key(state
->cli
, state
->session_key_krb5
);
1493 if (cli_simple_set_signing(state
->cli
, state
->session_key_krb5
,
1495 && !cli_check_sign_mac(state
->cli
, inbuf
, 1)) {
1496 TALLOC_FREE(subreq
);
1497 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1500 TALLOC_FREE(subreq
);
1501 tevent_req_done(req
);
1504 static ADS_STATUS
cli_session_setup_kerberos_recv(struct tevent_req
*req
)
1506 struct cli_session_setup_kerberos_state
*state
= tevent_req_data(
1507 req
, struct cli_session_setup_kerberos_state
);
1510 if (tevent_req_is_nterror(req
, &status
)) {
1511 return ADS_ERROR_NT(status
);
1513 return state
->ads_status
;
1516 static ADS_STATUS
cli_session_setup_kerberos(struct cli_state
*cli
,
1517 const char *principal
,
1518 const char *workgroup
)
1520 struct tevent_context
*ev
;
1521 struct tevent_req
*req
;
1522 ADS_STATUS status
= ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
1524 if (cli_has_async_calls(cli
)) {
1525 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
1527 ev
= tevent_context_init(talloc_tos());
1531 req
= cli_session_setup_kerberos_send(ev
, ev
, cli
, principal
,
1536 if (!tevent_req_poll(req
, ev
)) {
1537 status
= ADS_ERROR_SYSTEM(errno
);
1540 status
= cli_session_setup_kerberos_recv(req
);
1545 #endif /* HAVE_KRB5 */
1547 /****************************************************************************
1548 Do a spnego/NTLMSSP encrypted session setup.
1549 ****************************************************************************/
1551 struct cli_session_setup_ntlmssp_state
{
1552 struct tevent_context
*ev
;
1553 struct cli_state
*cli
;
1554 struct ntlmssp_state
*ntlmssp_state
;
1559 static int cli_session_setup_ntlmssp_state_destructor(
1560 struct cli_session_setup_ntlmssp_state
*state
)
1562 if (state
->ntlmssp_state
!= NULL
) {
1563 TALLOC_FREE(state
->ntlmssp_state
);
1568 static void cli_session_setup_ntlmssp_done(struct tevent_req
*req
);
1570 static struct tevent_req
*cli_session_setup_ntlmssp_send(
1571 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
, struct cli_state
*cli
,
1572 const char *user
, const char *pass
, const char *domain
)
1574 struct tevent_req
*req
, *subreq
;
1575 struct cli_session_setup_ntlmssp_state
*state
;
1578 const char *OIDs_ntlm
[] = {OID_NTLMSSP
, NULL
};
1580 req
= tevent_req_create(mem_ctx
, &state
,
1581 struct cli_session_setup_ntlmssp_state
);
1589 state
->ntlmssp_state
= NULL
;
1590 talloc_set_destructor(
1591 state
, cli_session_setup_ntlmssp_state_destructor
);
1593 cli_temp_set_signing(cli
);
1595 status
= ntlmssp_client_start(state
,
1598 lp_client_ntlmv2_auth(),
1599 &state
->ntlmssp_state
);
1600 if (!NT_STATUS_IS_OK(status
)) {
1603 ntlmssp_want_feature(state
->ntlmssp_state
,
1604 NTLMSSP_FEATURE_SESSION_KEY
);
1605 if (cli
->use_ccache
) {
1606 ntlmssp_want_feature(state
->ntlmssp_state
,
1607 NTLMSSP_FEATURE_CCACHE
);
1609 status
= ntlmssp_set_username(state
->ntlmssp_state
, user
);
1610 if (!NT_STATUS_IS_OK(status
)) {
1613 status
= ntlmssp_set_domain(state
->ntlmssp_state
, domain
);
1614 if (!NT_STATUS_IS_OK(status
)) {
1617 status
= ntlmssp_set_password(state
->ntlmssp_state
, pass
);
1618 if (!NT_STATUS_IS_OK(status
)) {
1621 status
= ntlmssp_update(state
->ntlmssp_state
, data_blob_null
,
1623 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1627 state
->blob_out
= spnego_gen_negTokenInit(state
, OIDs_ntlm
, &blob_out
, NULL
);
1628 data_blob_free(&blob_out
);
1630 subreq
= cli_sesssetup_blob_send(state
, ev
, cli
, state
->blob_out
);
1631 if (tevent_req_nomem(subreq
, req
)) {
1632 return tevent_req_post(req
, ev
);
1634 tevent_req_set_callback(subreq
, cli_session_setup_ntlmssp_done
, req
);
1637 tevent_req_nterror(req
, status
);
1638 return tevent_req_post(req
, ev
);
1641 static void cli_session_setup_ntlmssp_done(struct tevent_req
*subreq
)
1643 struct tevent_req
*req
= tevent_req_callback_data(
1644 subreq
, struct tevent_req
);
1645 struct cli_session_setup_ntlmssp_state
*state
= tevent_req_data(
1646 req
, struct cli_session_setup_ntlmssp_state
);
1647 DATA_BLOB blob_in
, msg_in
, blob_out
;
1652 status
= cli_sesssetup_blob_recv(subreq
, talloc_tos(), &blob_in
,
1654 TALLOC_FREE(subreq
);
1655 data_blob_free(&state
->blob_out
);
1657 if (NT_STATUS_IS_OK(status
)) {
1658 if (state
->cli
->server_domain
[0] == '\0') {
1659 TALLOC_FREE(state
->cli
->server_domain
);
1660 state
->cli
->server_domain
= talloc_strdup(state
->cli
,
1661 state
->ntlmssp_state
->server
.netbios_domain
);
1662 if (state
->cli
->server_domain
== NULL
) {
1663 TALLOC_FREE(subreq
);
1664 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
1668 cli_set_session_key(
1669 state
->cli
, state
->ntlmssp_state
->session_key
);
1671 if (cli_simple_set_signing(
1672 state
->cli
, state
->ntlmssp_state
->session_key
,
1674 && !cli_check_sign_mac(state
->cli
, inbuf
, 1)) {
1675 TALLOC_FREE(subreq
);
1676 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1679 TALLOC_FREE(subreq
);
1680 TALLOC_FREE(state
->ntlmssp_state
);
1681 tevent_req_done(req
);
1684 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1685 tevent_req_nterror(req
, status
);
1689 if (blob_in
.length
== 0) {
1690 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
1694 if ((state
->turn
== 1)
1695 && NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1696 DATA_BLOB tmp_blob
= data_blob_null
;
1697 /* the server might give us back two challenges */
1698 parse_ret
= spnego_parse_challenge(state
, blob_in
, &msg_in
,
1700 data_blob_free(&tmp_blob
);
1702 parse_ret
= spnego_parse_auth_response(state
, blob_in
, status
,
1703 OID_NTLMSSP
, &msg_in
);
1708 DEBUG(3,("Failed to parse auth response\n"));
1709 if (NT_STATUS_IS_OK(status
)
1710 || NT_STATUS_EQUAL(status
,
1711 NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1713 req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
1718 status
= ntlmssp_update(state
->ntlmssp_state
, msg_in
, &blob_out
);
1720 if (!NT_STATUS_IS_OK(status
)
1721 && !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1722 TALLOC_FREE(subreq
);
1723 TALLOC_FREE(state
->ntlmssp_state
);
1724 tevent_req_nterror(req
, status
);
1728 state
->blob_out
= spnego_gen_auth(state
, blob_out
);
1729 TALLOC_FREE(subreq
);
1730 if (tevent_req_nomem(state
->blob_out
.data
, req
)) {
1734 subreq
= cli_sesssetup_blob_send(state
, state
->ev
, state
->cli
,
1736 if (tevent_req_nomem(subreq
, req
)) {
1739 tevent_req_set_callback(subreq
, cli_session_setup_ntlmssp_done
, req
);
1742 static NTSTATUS
cli_session_setup_ntlmssp_recv(struct tevent_req
*req
)
1744 struct cli_session_setup_ntlmssp_state
*state
= tevent_req_data(
1745 req
, struct cli_session_setup_ntlmssp_state
);
1748 if (tevent_req_is_nterror(req
, &status
)) {
1749 state
->cli
->vuid
= 0;
1752 return NT_STATUS_OK
;
1755 static NTSTATUS
cli_session_setup_ntlmssp(struct cli_state
*cli
,
1760 struct tevent_context
*ev
;
1761 struct tevent_req
*req
;
1762 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1764 if (cli_has_async_calls(cli
)) {
1765 return NT_STATUS_INVALID_PARAMETER
;
1767 ev
= tevent_context_init(talloc_tos());
1771 req
= cli_session_setup_ntlmssp_send(ev
, ev
, cli
, user
, pass
, domain
);
1775 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1778 status
= cli_session_setup_ntlmssp_recv(req
);
1784 /****************************************************************************
1785 Do a spnego encrypted session setup.
1787 user_domain: The shortname of the domain the user/machine is a member of.
1788 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1789 ****************************************************************************/
1791 ADS_STATUS
cli_session_setup_spnego(struct cli_state
*cli
, const char *user
,
1792 const char *pass
, const char *user_domain
,
1793 const char * dest_realm
)
1795 char *principal
= NULL
;
1796 char *OIDs
[ASN1_MAX_OIDS
];
1799 const char *p
= NULL
;
1800 char *account
= NULL
;
1803 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli
->secblob
.length
));
1805 /* the server might not even do spnego */
1806 if (cli
->secblob
.length
<= 16) {
1807 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1812 file_save("negprot.dat", cli
->secblob
.data
, cli
->secblob
.length
);
1815 /* there is 16 bytes of GUID before the real spnego packet starts */
1816 blob
= data_blob(cli
->secblob
.data
+16, cli
->secblob
.length
-16);
1818 /* The server sent us the first part of the SPNEGO exchange in the
1819 * negprot reply. It is WRONG to depend on the principal sent in the
1820 * negprot reply, but right now we do it. If we don't receive one,
1821 * we try to best guess, then fall back to NTLM. */
1822 if (!spnego_parse_negTokenInit(talloc_tos(), blob
, OIDs
, &principal
, NULL
) ||
1824 data_blob_free(&blob
);
1825 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
1827 data_blob_free(&blob
);
1829 /* make sure the server understands kerberos */
1830 for (i
=0;OIDs
[i
];i
++) {
1832 DEBUG(3,("got OID=%s\n", OIDs
[i
]));
1834 DEBUGADD(3,("got OID=%s\n", OIDs
[i
]));
1835 if (strcmp(OIDs
[i
], OID_KERBEROS5_OLD
) == 0 ||
1836 strcmp(OIDs
[i
], OID_KERBEROS5
) == 0) {
1837 cli
->got_kerberos_mechanism
= True
;
1839 talloc_free(OIDs
[i
]);
1842 DEBUG(3,("got principal=%s\n", principal
? principal
: "<null>"));
1844 status
= cli_set_username(cli
, user
);
1845 if (!NT_STATUS_IS_OK(status
)) {
1846 TALLOC_FREE(principal
);
1847 return ADS_ERROR_NT(status
);
1851 /* If password is set we reauthenticate to kerberos server
1852 * and do not store results */
1854 if (cli
->got_kerberos_mechanism
&& cli
->use_kerberos
) {
1857 if (pass
&& *pass
) {
1860 use_in_memory_ccache();
1861 ret
= kerberos_kinit_password(user
, pass
, 0 /* no time correction for now */, NULL
);
1864 TALLOC_FREE(principal
);
1865 DEBUG(0, ("Kinit failed: %s\n", error_message(ret
)));
1866 if (cli
->fallback_after_kerberos
)
1868 return ADS_ERROR_KRB5(ret
);
1872 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1874 if (!lp_client_use_spnego_principal() || strequal(principal
, ADS_IGNORE_PRINCIPAL
)) {
1875 TALLOC_FREE(principal
);
1878 if (principal
== NULL
&&
1879 !is_ipaddress(cli
->desthost
) &&
1880 !strequal(STAR_SMBSERVER
,
1884 DEBUG(3,("cli_session_setup_spnego: using target "
1885 "hostname not SPNEGO principal\n"));
1887 host
= strchr_m(cli
->desthost
, '.');
1889 realm
= SMB_STRDUP(dest_realm
);
1891 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
1897 realm
= kerberos_get_realm_from_hostname(cli
->desthost
);
1899 /* NetBIOS name - use our realm. */
1900 realm
= kerberos_get_default_realm_from_ccache();
1904 if (realm
== NULL
|| *realm
== '\0') {
1905 realm
= SMB_STRDUP(lp_realm());
1907 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
1910 DEBUG(3,("cli_session_setup_spnego: cannot "
1911 "get realm from dest_realm %s, "
1912 "desthost %s. Using default "
1913 "smb.conf realm %s\n",
1914 dest_realm
? dest_realm
: "<null>",
1919 principal
= talloc_asprintf(talloc_tos(),
1925 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
1927 DEBUG(3,("cli_session_setup_spnego: guessed "
1928 "server principal=%s\n",
1929 principal
? principal
: "<null>"));
1935 rc
= cli_session_setup_kerberos(cli
, principal
,
1937 if (ADS_ERR_OK(rc
) || !cli
->fallback_after_kerberos
) {
1938 TALLOC_FREE(principal
);
1945 TALLOC_FREE(principal
);
1949 account
= talloc_strdup(talloc_tos(), user
);
1951 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
1954 /* when falling back to ntlmssp while authenticating with a machine
1955 * account strip off the realm - gd */
1957 if ((p
= strchr_m(user
, '@')) != NULL
) {
1958 account
[PTR_DIFF(p
,user
)] = '\0';
1961 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli
, account
, pass
, user_domain
));
1964 /****************************************************************************
1965 Send a session setup. The username and workgroup is in UNIX character
1966 format and must be converted to DOS codepage format before sending. If the
1967 password is in plaintext, the same should be done.
1968 ****************************************************************************/
1970 NTSTATUS
cli_session_setup(struct cli_state
*cli
,
1972 const char *pass
, int passlen
,
1973 const char *ntpass
, int ntpasslen
,
1974 const char *workgroup
)
1980 user2
= talloc_strdup(talloc_tos(), user
);
1982 user2
= talloc_strdup(talloc_tos(), "");
1984 if (user2
== NULL
) {
1985 return NT_STATUS_NO_MEMORY
;
1992 /* allow for workgroups as part of the username */
1993 if ((p
=strchr_m(user2
,'\\')) || (p
=strchr_m(user2
,'/')) ||
1994 (p
=strchr_m(user2
,*lp_winbind_separator()))) {
2001 if (cli
->protocol
< PROTOCOL_LANMAN1
) {
2003 * Ensure cli->server_domain,
2004 * cli->server_os and cli->server_type
2005 * are valid pointers.
2007 cli
->server_domain
= talloc_strdup(cli
, "");
2008 cli
->server_os
= talloc_strdup(cli
, "");
2009 cli
->server_type
= talloc_strdup(cli
, "");
2010 if (cli
->server_domain
== NULL
||
2011 cli
->server_os
== NULL
||
2012 cli
->server_type
== NULL
) {
2013 return NT_STATUS_NO_MEMORY
;
2015 return NT_STATUS_OK
;
2018 /* now work out what sort of session setup we are going to
2019 do. I have split this into separate functions to make the
2020 flow a bit easier to understand (tridge) */
2022 /* if its an older server then we have to use the older request format */
2024 if (cli
->protocol
< PROTOCOL_NT1
) {
2025 if (!lp_client_lanman_auth() && passlen
!= 24 && (*pass
)) {
2026 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2027 " or 'client ntlmv2 auth = yes'\n"));
2028 return NT_STATUS_ACCESS_DENIED
;
2031 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) == 0 &&
2032 !lp_client_plaintext_auth() && (*pass
)) {
2033 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2034 " or 'client ntlmv2 auth = yes'\n"));
2035 return NT_STATUS_ACCESS_DENIED
;
2038 return cli_session_setup_lanman2(cli
, user
, pass
, passlen
,
2042 /* if no user is supplied then we have to do an anonymous connection.
2043 passwords are ignored */
2045 if (!user
|| !*user
)
2046 return cli_session_setup_guest(cli
);
2048 /* if the server is share level then send a plaintext null
2049 password at this point. The password is sent in the tree
2052 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
) == 0)
2053 return cli_session_setup_plain(cli
, user
, "", workgroup
);
2055 /* if the server doesn't support encryption then we have to use
2056 plaintext. The second password is ignored */
2058 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) == 0) {
2059 if (!lp_client_plaintext_auth() && (*pass
)) {
2060 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2061 " or 'client ntlmv2 auth = yes'\n"));
2062 return NT_STATUS_ACCESS_DENIED
;
2064 return cli_session_setup_plain(cli
, user
, pass
, workgroup
);
2067 /* if the server supports extended security then use SPNEGO */
2069 if (cli
->capabilities
& CAP_EXTENDED_SECURITY
) {
2070 ADS_STATUS status
= cli_session_setup_spnego(cli
, user
, pass
,
2072 if (!ADS_ERR_OK(status
)) {
2073 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status
)));
2074 return ads_ntstatus(status
);
2079 /* otherwise do a NT1 style session setup */
2080 status
= cli_session_setup_nt1(cli
, user
, pass
, passlen
,
2081 ntpass
, ntpasslen
, workgroup
);
2082 if (!NT_STATUS_IS_OK(status
)) {
2083 DEBUG(3,("cli_session_setup: NT1 session setup "
2084 "failed: %s\n", nt_errstr(status
)));
2089 if (strstr(cli
->server_type
, "Samba")) {
2090 cli
->is_samba
= True
;
2093 return NT_STATUS_OK
;
2096 /****************************************************************************
2098 *****************************************************************************/
2100 struct cli_ulogoff_state
{
2101 struct cli_state
*cli
;
2105 static void cli_ulogoff_done(struct tevent_req
*subreq
);
2107 struct tevent_req
*cli_ulogoff_send(TALLOC_CTX
*mem_ctx
,
2108 struct tevent_context
*ev
,
2109 struct cli_state
*cli
)
2111 struct tevent_req
*req
, *subreq
;
2112 struct cli_ulogoff_state
*state
;
2114 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ulogoff_state
);
2120 SCVAL(state
->vwv
+0, 0, 0xFF);
2121 SCVAL(state
->vwv
+1, 0, 0);
2122 SSVAL(state
->vwv
+2, 0, 0);
2124 subreq
= cli_smb_send(state
, ev
, cli
, SMBulogoffX
, 0, 2, state
->vwv
,
2126 if (tevent_req_nomem(subreq
, req
)) {
2127 return tevent_req_post(req
, ev
);
2129 tevent_req_set_callback(subreq
, cli_ulogoff_done
, req
);
2133 static void cli_ulogoff_done(struct tevent_req
*subreq
)
2135 struct tevent_req
*req
= tevent_req_callback_data(
2136 subreq
, struct tevent_req
);
2137 struct cli_ulogoff_state
*state
= tevent_req_data(
2138 req
, struct cli_ulogoff_state
);
2141 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2142 if (!NT_STATUS_IS_OK(status
)) {
2143 tevent_req_nterror(req
, status
);
2146 state
->cli
->vuid
= -1;
2147 tevent_req_done(req
);
2150 NTSTATUS
cli_ulogoff_recv(struct tevent_req
*req
)
2152 return tevent_req_simple_recv_ntstatus(req
);
2155 NTSTATUS
cli_ulogoff(struct cli_state
*cli
)
2157 struct tevent_context
*ev
;
2158 struct tevent_req
*req
;
2159 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2161 if (cli_has_async_calls(cli
)) {
2162 return NT_STATUS_INVALID_PARAMETER
;
2164 ev
= tevent_context_init(talloc_tos());
2168 req
= cli_ulogoff_send(ev
, ev
, cli
);
2172 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2175 status
= cli_ulogoff_recv(req
);
2181 /****************************************************************************
2183 ****************************************************************************/
2185 struct cli_tcon_andx_state
{
2186 struct cli_state
*cli
;
2191 static void cli_tcon_andx_done(struct tevent_req
*subreq
);
2193 struct tevent_req
*cli_tcon_andx_create(TALLOC_CTX
*mem_ctx
,
2194 struct event_context
*ev
,
2195 struct cli_state
*cli
,
2196 const char *share
, const char *dev
,
2197 const char *pass
, int passlen
,
2198 struct tevent_req
**psmbreq
)
2200 struct tevent_req
*req
, *subreq
;
2201 struct cli_tcon_andx_state
*state
;
2209 req
= tevent_req_create(mem_ctx
, &state
, struct cli_tcon_andx_state
);
2216 cli
->share
= talloc_strdup(cli
, share
);
2221 /* in user level security don't send a password now */
2222 if (cli
->sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
) {
2225 } else if (pass
== NULL
) {
2226 DEBUG(1, ("Server not using user level security and no "
2227 "password supplied.\n"));
2231 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) &&
2232 *pass
&& passlen
!= 24) {
2233 if (!lp_client_lanman_auth()) {
2234 DEBUG(1, ("Server requested LANMAN password "
2235 "(share-level security) but "
2236 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2241 * Non-encrypted passwords - convert to DOS codepage before
2244 SMBencrypt(pass
, cli
->secblob
.data
, p24
);
2246 pass
= (const char *)p24
;
2248 if((cli
->sec_mode
& (NEGOTIATE_SECURITY_USER_LEVEL
2249 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
))
2253 if (!lp_client_plaintext_auth() && (*pass
)) {
2254 DEBUG(1, ("Server requested plaintext "
2256 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2261 * Non-encrypted passwords - convert to DOS codepage
2264 tmp_pass
= talloc_array(talloc_tos(), char, 128);
2265 if (tmp_pass
== NULL
) {
2266 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
2267 return tevent_req_post(req
, ev
);
2269 passlen
= clistr_push(cli
,
2272 talloc_get_size(tmp_pass
),
2274 if (passlen
== -1) {
2275 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
2276 return tevent_req_post(req
, ev
);
2282 SCVAL(vwv
+0, 0, 0xFF);
2285 SSVAL(vwv
+2, 0, TCONX_FLAG_EXTENDED_RESPONSE
);
2286 SSVAL(vwv
+3, 0, passlen
);
2288 if (passlen
&& pass
) {
2289 bytes
= (uint8_t *)talloc_memdup(state
, pass
, passlen
);
2291 bytes
= talloc_array(state
, uint8_t, 0);
2297 tmp
= talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2298 cli
->desthost
, share
);
2303 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), tmp
, strlen(tmp
)+1,
2308 * Add the devicetype
2310 tmp
= talloc_strdup_upper(talloc_tos(), dev
);
2315 bytes
= smb_bytes_push_str(bytes
, false, tmp
, strlen(tmp
)+1, NULL
);
2318 if (bytes
== NULL
) {
2323 state
->bytes
.iov_base
= (void *)bytes
;
2324 state
->bytes
.iov_len
= talloc_get_size(bytes
);
2326 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBtconX
, 0, 4, vwv
,
2328 if (subreq
== NULL
) {
2332 tevent_req_set_callback(subreq
, cli_tcon_andx_done
, req
);
2337 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2338 return tevent_req_post(req
, ev
);
2341 struct tevent_req
*cli_tcon_andx_send(TALLOC_CTX
*mem_ctx
,
2342 struct event_context
*ev
,
2343 struct cli_state
*cli
,
2344 const char *share
, const char *dev
,
2345 const char *pass
, int passlen
)
2347 struct tevent_req
*req
, *subreq
;
2350 req
= cli_tcon_andx_create(mem_ctx
, ev
, cli
, share
, dev
, pass
, passlen
,
2355 if (subreq
== NULL
) {
2358 status
= cli_smb_req_send(subreq
);
2359 if (!NT_STATUS_IS_OK(status
)) {
2360 tevent_req_nterror(req
, status
);
2361 return tevent_req_post(req
, ev
);
2366 static void cli_tcon_andx_done(struct tevent_req
*subreq
)
2368 struct tevent_req
*req
= tevent_req_callback_data(
2369 subreq
, struct tevent_req
);
2370 struct cli_tcon_andx_state
*state
= tevent_req_data(
2371 req
, struct cli_tcon_andx_state
);
2372 struct cli_state
*cli
= state
->cli
;
2381 status
= cli_smb_recv(subreq
, state
, &in
, 0, &wct
, &vwv
,
2382 &num_bytes
, &bytes
);
2383 TALLOC_FREE(subreq
);
2384 if (!NT_STATUS_IS_OK(status
)) {
2385 tevent_req_nterror(req
, status
);
2392 if (clistr_pull_talloc(cli
,
2394 SVAL(inbuf
, smb_flg2
),
2398 STR_TERMINATE
|STR_ASCII
) == -1) {
2399 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
2403 cli
->dev
= talloc_strdup(cli
, "");
2404 if (cli
->dev
== NULL
) {
2405 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
2410 if ((cli
->protocol
>= PROTOCOL_NT1
) && (num_bytes
== 3)) {
2411 /* almost certainly win95 - enable bug fixes */
2416 * Make sure that we have the optional support 16-bit field. WCT > 2.
2417 * Avoids issues when connecting to Win9x boxes sharing files
2420 cli
->dfsroot
= false;
2422 if ((wct
> 2) && (cli
->protocol
>= PROTOCOL_LANMAN2
)) {
2423 cli
->dfsroot
= ((SVAL(vwv
+2, 0) & SMB_SHARE_IN_DFS
) != 0);
2426 cli
->cnum
= SVAL(inbuf
,smb_tid
);
2427 tevent_req_done(req
);
2430 NTSTATUS
cli_tcon_andx_recv(struct tevent_req
*req
)
2432 return tevent_req_simple_recv_ntstatus(req
);
2435 NTSTATUS
cli_tcon_andx(struct cli_state
*cli
, const char *share
,
2436 const char *dev
, const char *pass
, int passlen
)
2438 TALLOC_CTX
*frame
= talloc_stackframe();
2439 struct event_context
*ev
;
2440 struct tevent_req
*req
;
2441 NTSTATUS status
= NT_STATUS_OK
;
2443 if (cli_has_async_calls(cli
)) {
2445 * Can't use sync call while an async call is in flight
2447 status
= NT_STATUS_INVALID_PARAMETER
;
2451 ev
= event_context_init(frame
);
2453 status
= NT_STATUS_NO_MEMORY
;
2457 req
= cli_tcon_andx_send(frame
, ev
, cli
, share
, dev
, pass
, passlen
);
2459 status
= NT_STATUS_NO_MEMORY
;
2463 if (!tevent_req_poll(req
, ev
)) {
2464 status
= map_nt_error_from_unix(errno
);
2468 status
= cli_tcon_andx_recv(req
);
2474 /****************************************************************************
2475 Send a tree disconnect.
2476 ****************************************************************************/
2478 struct cli_tdis_state
{
2479 struct cli_state
*cli
;
2482 static void cli_tdis_done(struct tevent_req
*subreq
);
2484 struct tevent_req
*cli_tdis_send(TALLOC_CTX
*mem_ctx
,
2485 struct tevent_context
*ev
,
2486 struct cli_state
*cli
)
2488 struct tevent_req
*req
, *subreq
;
2489 struct cli_tdis_state
*state
;
2491 req
= tevent_req_create(mem_ctx
, &state
, struct cli_tdis_state
);
2497 subreq
= cli_smb_send(state
, ev
, cli
, SMBtdis
, 0, 0, NULL
, 0, NULL
);
2498 if (tevent_req_nomem(subreq
, req
)) {
2499 return tevent_req_post(req
, ev
);
2501 tevent_req_set_callback(subreq
, cli_tdis_done
, req
);
2505 static void cli_tdis_done(struct tevent_req
*subreq
)
2507 struct tevent_req
*req
= tevent_req_callback_data(
2508 subreq
, struct tevent_req
);
2509 struct cli_tdis_state
*state
= tevent_req_data(
2510 req
, struct cli_tdis_state
);
2513 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2514 TALLOC_FREE(subreq
);
2515 if (!NT_STATUS_IS_OK(status
)) {
2516 tevent_req_nterror(req
, status
);
2519 state
->cli
->cnum
= -1;
2520 tevent_req_done(req
);
2523 NTSTATUS
cli_tdis_recv(struct tevent_req
*req
)
2525 return tevent_req_simple_recv_ntstatus(req
);
2528 NTSTATUS
cli_tdis(struct cli_state
*cli
)
2530 struct tevent_context
*ev
;
2531 struct tevent_req
*req
;
2532 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2534 if (cli_has_async_calls(cli
)) {
2535 return NT_STATUS_INVALID_PARAMETER
;
2537 ev
= tevent_context_init(talloc_tos());
2541 req
= cli_tdis_send(ev
, ev
, cli
);
2545 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2548 status
= cli_tdis_recv(req
);
2554 /****************************************************************************
2555 Send a negprot command.
2556 ****************************************************************************/
2558 struct cli_negprot_state
{
2559 struct cli_state
*cli
;
2562 static void cli_negprot_done(struct tevent_req
*subreq
);
2564 struct tevent_req
*cli_negprot_send(TALLOC_CTX
*mem_ctx
,
2565 struct event_context
*ev
,
2566 struct cli_state
*cli
)
2568 struct tevent_req
*req
, *subreq
;
2569 struct cli_negprot_state
*state
;
2570 uint8_t *bytes
= NULL
;
2574 req
= tevent_req_create(mem_ctx
, &state
, struct cli_negprot_state
);
2580 if (cli
->protocol
< PROTOCOL_NT1
)
2581 cli
->use_spnego
= False
;
2583 /* setup the protocol strings */
2584 for (numprots
=0; numprots
< ARRAY_SIZE(prots
); numprots
++) {
2586 if (prots
[numprots
].prot
> cli
->protocol
) {
2589 bytes
= (uint8_t *)talloc_append_blob(
2590 state
, bytes
, data_blob_const(&c
, sizeof(c
)));
2591 if (tevent_req_nomem(bytes
, req
)) {
2592 return tevent_req_post(req
, ev
);
2594 bytes
= smb_bytes_push_str(bytes
, false,
2595 prots
[numprots
].name
,
2596 strlen(prots
[numprots
].name
)+1,
2598 if (tevent_req_nomem(bytes
, req
)) {
2599 return tevent_req_post(req
, ev
);
2606 subreq
= cli_smb_send(state
, ev
, cli
, SMBnegprot
, 0, 0, NULL
,
2607 talloc_get_size(bytes
), bytes
);
2610 if (tevent_req_nomem(subreq
, req
)) {
2611 return tevent_req_post(req
, ev
);
2613 tevent_req_set_callback(subreq
, cli_negprot_done
, req
);
2617 static void cli_negprot_done(struct tevent_req
*subreq
)
2619 struct tevent_req
*req
= tevent_req_callback_data(
2620 subreq
, struct tevent_req
);
2621 struct cli_negprot_state
*state
= tevent_req_data(
2622 req
, struct cli_negprot_state
);
2623 struct cli_state
*cli
= state
->cli
;
2632 status
= cli_smb_recv(subreq
, state
, &inbuf
, 1, &wct
, &vwv
,
2633 &num_bytes
, &bytes
);
2634 TALLOC_FREE(subreq
);
2635 if (!NT_STATUS_IS_OK(status
)) {
2636 tevent_req_nterror(req
, status
);
2640 protnum
= SVAL(vwv
, 0);
2642 if ((protnum
>= ARRAY_SIZE(prots
))
2643 || (prots
[protnum
].prot
> cli
->protocol
)) {
2644 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
2648 cli
->protocol
= prots
[protnum
].prot
;
2650 if ((cli
->protocol
< PROTOCOL_NT1
) &&
2651 client_is_signing_mandatory(cli
)) {
2652 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2653 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2657 if (cli
->protocol
>= PROTOCOL_NT1
) {
2659 bool negotiated_smb_signing
= false;
2660 DATA_BLOB blob
= data_blob_null
;
2663 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
2668 cli
->sec_mode
= CVAL(vwv
+ 1, 0);
2669 cli
->max_mux
= SVAL(vwv
+ 1, 1);
2670 cli
->max_xmit
= IVAL(vwv
+ 3, 1);
2671 cli
->sesskey
= IVAL(vwv
+ 7, 1);
2672 cli
->serverzone
= SVALS(vwv
+ 15, 1);
2673 cli
->serverzone
*= 60;
2674 /* this time arrives in real GMT */
2675 ts
= interpret_long_date(((char *)(vwv
+11))+1);
2676 cli
->servertime
= ts
.tv_sec
;
2677 cli
->secblob
= data_blob(bytes
, num_bytes
);
2678 cli
->capabilities
= IVAL(vwv
+ 9, 1);
2679 if (cli
->capabilities
& CAP_RAW_MODE
) {
2680 cli
->readbraw_supported
= True
;
2681 cli
->writebraw_supported
= True
;
2683 /* work out if they sent us a workgroup */
2684 if (!(cli
->capabilities
& CAP_EXTENDED_SECURITY
) &&
2685 smb_buflen(inbuf
) > 8) {
2686 blob
= data_blob_const(bytes
+ 8, num_bytes
- 8);
2689 if (blob
.length
> 0) {
2691 char *server_domain
= NULL
;
2693 ret
= clistr_pull_talloc(cli
,
2694 (const char *)inbuf
,
2695 SVAL(inbuf
, smb_flg2
),
2703 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
2706 if (server_domain
) {
2707 cli
->server_domain
= server_domain
;
2712 * As signing is slow we only turn it on if either the client or
2713 * the server require it. JRA.
2716 if (cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_REQUIRED
) {
2717 /* Fail if server says signing is mandatory and we don't want to support it. */
2718 if (!client_is_signing_allowed(cli
)) {
2719 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2720 tevent_req_nterror(req
,
2721 NT_STATUS_ACCESS_DENIED
);
2724 negotiated_smb_signing
= true;
2725 } else if (client_is_signing_mandatory(cli
) && client_is_signing_allowed(cli
)) {
2726 /* Fail if client says signing is mandatory and the server doesn't support it. */
2727 if (!(cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_ENABLED
)) {
2728 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2729 tevent_req_nterror(req
,
2730 NT_STATUS_ACCESS_DENIED
);
2733 negotiated_smb_signing
= true;
2734 } else if (cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_ENABLED
) {
2735 negotiated_smb_signing
= true;
2738 if (negotiated_smb_signing
) {
2739 cli_set_signing_negotiated(cli
);
2742 if (cli
->capabilities
& (CAP_LARGE_READX
|CAP_LARGE_WRITEX
)) {
2743 SAFE_FREE(cli
->outbuf
);
2744 SAFE_FREE(cli
->inbuf
);
2745 cli
->outbuf
= (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE
+LARGE_WRITEX_HDR_SIZE
+SAFETY_MARGIN
);
2746 cli
->inbuf
= (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE
+LARGE_WRITEX_HDR_SIZE
+SAFETY_MARGIN
);
2747 if (!cli
->outbuf
|| !cli
->inbuf
) {
2748 tevent_req_nterror(req
,
2749 NT_STATUS_NO_MEMORY
);
2752 cli
->bufsize
= CLI_SAMBA_MAX_LARGE_READX_SIZE
+ LARGE_WRITEX_HDR_SIZE
;
2755 } else if (cli
->protocol
>= PROTOCOL_LANMAN1
) {
2757 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
2761 cli
->use_spnego
= False
;
2762 cli
->sec_mode
= SVAL(vwv
+ 1, 0);
2763 cli
->max_xmit
= SVAL(vwv
+ 2, 0);
2764 cli
->max_mux
= SVAL(vwv
+ 3, 0);
2765 cli
->sesskey
= IVAL(vwv
+ 6, 0);
2766 cli
->serverzone
= SVALS(vwv
+ 10, 0);
2767 cli
->serverzone
*= 60;
2768 /* this time is converted to GMT by make_unix_date */
2769 cli
->servertime
= make_unix_date(
2770 (char *)(vwv
+ 8), cli
->serverzone
);
2771 cli
->readbraw_supported
= ((SVAL(vwv
+ 5, 0) & 0x1) != 0);
2772 cli
->writebraw_supported
= ((SVAL(vwv
+ 5, 0) & 0x2) != 0);
2773 cli
->secblob
= data_blob(bytes
, num_bytes
);
2775 /* the old core protocol */
2776 cli
->use_spnego
= False
;
2778 cli
->serverzone
= get_time_zone(time(NULL
));
2781 cli
->max_xmit
= MIN(cli
->max_xmit
, CLI_BUFFER_SIZE
);
2783 /* a way to force ascii SMB */
2784 if (getenv("CLI_FORCE_ASCII"))
2785 cli
->capabilities
&= ~CAP_UNICODE
;
2787 tevent_req_done(req
);
2790 NTSTATUS
cli_negprot_recv(struct tevent_req
*req
)
2792 return tevent_req_simple_recv_ntstatus(req
);
2795 NTSTATUS
cli_negprot(struct cli_state
*cli
)
2797 TALLOC_CTX
*frame
= talloc_stackframe();
2798 struct event_context
*ev
;
2799 struct tevent_req
*req
;
2800 NTSTATUS status
= NT_STATUS_OK
;
2802 if (cli_has_async_calls(cli
)) {
2804 * Can't use sync call while an async call is in flight
2806 status
= NT_STATUS_INVALID_PARAMETER
;
2810 ev
= event_context_init(frame
);
2812 status
= NT_STATUS_NO_MEMORY
;
2816 req
= cli_negprot_send(frame
, ev
, cli
);
2818 status
= NT_STATUS_NO_MEMORY
;
2822 if (!tevent_req_poll(req
, ev
)) {
2823 status
= map_nt_error_from_unix(errno
);
2827 status
= cli_negprot_recv(req
);
2833 /****************************************************************************
2834 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
2835 ****************************************************************************/
2837 bool cli_session_request(struct cli_state
*cli
,
2838 struct nmb_name
*calling
, struct nmb_name
*called
)
2845 /* 445 doesn't have session request */
2846 if (cli
->port
== 445)
2849 memcpy(&(cli
->calling
), calling
, sizeof(*calling
));
2850 memcpy(&(cli
->called
), called
, sizeof(*called
));
2852 /* put in the destination name */
2854 tmp
= name_mangle(talloc_tos(), cli
->called
.name
,
2855 cli
->called
.name_type
);
2860 p
= cli
->outbuf
+len
;
2861 namelen
= name_len((unsigned char *)tmp
, talloc_get_size(tmp
));
2863 memcpy(p
, tmp
, namelen
);
2870 tmp
= name_mangle(talloc_tos(), cli
->calling
.name
,
2871 cli
->calling
.name_type
);
2876 p
= cli
->outbuf
+len
;
2877 namelen
= name_len((unsigned char *)tmp
, talloc_get_size(tmp
));
2879 memcpy(p
, tmp
, namelen
);
2884 /* send a session request (RFC 1002) */
2885 /* setup the packet length
2886 * Remove four bytes from the length count, since the length
2887 * field in the NBT Session Service header counts the number
2888 * of bytes which follow. The cli_send_smb() function knows
2889 * about this and accounts for those four bytes.
2893 _smb_setlen(cli
->outbuf
,len
);
2894 SCVAL(cli
->outbuf
,0,0x81);
2897 DEBUG(5,("Sent session request\n"));
2899 if (!cli_receive_smb(cli
))
2902 if (CVAL(cli
->inbuf
,0) == 0x84) {
2903 /* C. Hoch 9/14/95 Start */
2904 /* For information, here is the response structure.
2905 * We do the byte-twiddling to for portability.
2906 struct RetargetResponse{
2908 unsigned char flags;
2914 uint16_t port
= (CVAL(cli
->inbuf
,8)<<8)+CVAL(cli
->inbuf
,9);
2915 struct in_addr dest_ip
;
2918 /* SESSION RETARGET */
2919 putip((char *)&dest_ip
,cli
->inbuf
+4);
2920 in_addr_to_sockaddr_storage(&cli
->dest_ss
, dest_ip
);
2922 status
= open_socket_out(&cli
->dest_ss
, port
,
2923 LONG_CONNECT_TIMEOUT
, &cli
->fd
);
2924 if (!NT_STATUS_IS_OK(status
)) {
2928 DEBUG(3,("Retargeted\n"));
2930 set_socket_options(cli
->fd
, lp_socket_options());
2937 DEBUG(0,("Retarget recursion - failing\n"));
2941 ret
= cli_session_request(cli
, calling
, called
);
2945 } /* C. Hoch 9/14/95 End */
2947 if (CVAL(cli
->inbuf
,0) != 0x82) {
2948 /* This is the wrong place to put the error... JRA. */
2949 cli
->rap_error
= CVAL(cli
->inbuf
,4);
2959 static void smb_sock_connected(struct tevent_req
*req
)
2961 struct fd_struct
*pfd
= tevent_req_callback_data(
2962 req
, struct fd_struct
);
2966 status
= open_socket_out_defer_recv(req
, &fd
);
2967 if (NT_STATUS_IS_OK(status
)) {
2972 static NTSTATUS
open_smb_socket(const struct sockaddr_storage
*pss
,
2973 uint16_t *port
, int timeout
, int *pfd
)
2975 struct event_context
*ev
;
2976 struct tevent_req
*r139
, *r445
;
2977 struct fd_struct
*fd139
, *fd445
;
2978 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2981 return open_socket_out(pss
, *port
, timeout
, pfd
);
2984 ev
= event_context_init(talloc_tos());
2986 return NT_STATUS_NO_MEMORY
;
2989 fd139
= talloc(ev
, struct fd_struct
);
2990 if (fd139
== NULL
) {
2995 fd445
= talloc(ev
, struct fd_struct
);
2996 if (fd445
== NULL
) {
3001 r445
= open_socket_out_defer_send(ev
, ev
, timeval_set(0, 0),
3003 r139
= open_socket_out_defer_send(ev
, ev
, timeval_set(0, 3000),
3005 if ((r445
== NULL
) || (r139
== NULL
)) {
3008 tevent_req_set_callback(r445
, smb_sock_connected
, fd445
);
3009 tevent_req_set_callback(r139
, smb_sock_connected
, fd139
);
3011 while ((fd445
->fd
== -1) && (fd139
->fd
== -1)
3012 && (tevent_req_is_in_progress(r139
)
3013 || tevent_req_is_in_progress(r445
))) {
3014 event_loop_once(ev
);
3017 if ((fd139
->fd
!= -1) && (fd445
->fd
!= -1)) {
3022 if (fd445
->fd
!= -1) {
3025 status
= NT_STATUS_OK
;
3028 if (fd139
->fd
!= -1) {
3031 status
= NT_STATUS_OK
;
3035 status
= open_socket_out_defer_recv(r445
, &fd445
->fd
);
3041 /****************************************************************************
3042 Open the client sockets.
3043 ****************************************************************************/
3045 NTSTATUS
cli_connect(struct cli_state
*cli
,
3047 struct sockaddr_storage
*dest_ss
)
3050 int name_type
= 0x20;
3051 TALLOC_CTX
*frame
= talloc_stackframe();
3052 unsigned int num_addrs
= 0;
3054 struct sockaddr_storage
*ss_arr
= NULL
;
3057 /* reasonable default hostname */
3059 host
= STAR_SMBSERVER
;
3062 cli
->desthost
= talloc_strdup(cli
, host
);
3063 if (cli
->desthost
== NULL
) {
3064 return NT_STATUS_NO_MEMORY
;
3067 /* allow hostnames of the form NAME#xx and do a netbios lookup */
3068 if ((p
= strchr(cli
->desthost
, '#'))) {
3069 name_type
= strtol(p
+1, NULL
, 16);
3073 if (!dest_ss
|| is_zero_addr(dest_ss
)) {
3074 NTSTATUS status
=resolve_name_list(frame
,
3079 if (!NT_STATUS_IS_OK(status
)) {
3081 return NT_STATUS_BAD_NETWORK_NAME
;
3085 ss_arr
= TALLOC_P(frame
, struct sockaddr_storage
);
3088 return NT_STATUS_NO_MEMORY
;
3093 for (i
= 0; i
< num_addrs
; i
++) {
3094 cli
->dest_ss
= ss_arr
[i
];
3095 if (getenv("LIBSMB_PROG")) {
3096 cli
->fd
= sock_exec(getenv("LIBSMB_PROG"));
3098 uint16_t port
= cli
->port
;
3100 status
= open_smb_socket(&cli
->dest_ss
, &port
,
3101 cli
->timeout
, &cli
->fd
);
3102 if (NT_STATUS_IS_OK(status
)) {
3106 if (cli
->fd
== -1) {
3107 char addr
[INET6_ADDRSTRLEN
];
3108 print_sockaddr(addr
, sizeof(addr
), &ss_arr
[i
]);
3109 DEBUG(2,("Error connecting to %s (%s)\n",
3110 dest_ss
?addr
:host
,strerror(errno
)));
3112 /* Exit from loop on first connection. */
3117 if (cli
->fd
== -1) {
3119 return map_nt_error_from_unix(errno
);
3123 *dest_ss
= cli
->dest_ss
;
3126 set_socket_options(cli
->fd
, lp_socket_options());
3129 return NT_STATUS_OK
;
3133 establishes a connection to after the negprot.
3134 @param output_cli A fully initialised cli structure, non-null only on success
3135 @param dest_host The netbios name of the remote host
3136 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3137 @param port (optional) The destination port (0 for default)
3139 NTSTATUS
cli_start_connection(struct cli_state
**output_cli
,
3140 const char *my_name
,
3141 const char *dest_host
,
3142 struct sockaddr_storage
*dest_ss
, int port
,
3143 int signing_state
, int flags
)
3146 struct nmb_name calling
;
3147 struct nmb_name called
;
3148 struct cli_state
*cli
;
3149 struct sockaddr_storage ss
;
3152 my_name
= global_myname();
3154 if (!(cli
= cli_initialise_ex(signing_state
))) {
3155 return NT_STATUS_NO_MEMORY
;
3158 make_nmb_name(&calling
, my_name
, 0x0);
3159 make_nmb_name(&called
, dest_host
, 0x20);
3161 cli_set_port(cli
, port
);
3162 cli_set_timeout(cli
, 10000); /* 10 seconds. */
3172 DEBUG(3,("Connecting to host=%s\n", dest_host
));
3174 nt_status
= cli_connect(cli
, dest_host
, &ss
);
3175 if (!NT_STATUS_IS_OK(nt_status
)) {
3176 char addr
[INET6_ADDRSTRLEN
];
3177 print_sockaddr(addr
, sizeof(addr
), &ss
);
3178 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
3179 nmb_namestr(&called
), addr
, nt_errstr(nt_status
) ));
3184 if (!cli_session_request(cli
, &calling
, &called
)) {
3186 DEBUG(1,("session request to %s failed (%s)\n",
3187 called
.name
, cli_errstr(cli
)));
3188 if ((p
=strchr(called
.name
, '.')) && !is_ipaddress(called
.name
)) {
3192 if (strcmp(called
.name
, STAR_SMBSERVER
)) {
3193 make_nmb_name(&called
, STAR_SMBSERVER
, 0x20);
3196 return NT_STATUS_BAD_NETWORK_NAME
;
3199 if (flags
& CLI_FULL_CONNECTION_DONT_SPNEGO
)
3200 cli
->use_spnego
= False
;
3201 else if (flags
& CLI_FULL_CONNECTION_USE_KERBEROS
)
3202 cli
->use_kerberos
= True
;
3204 if ((flags
& CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS
) &&
3205 cli
->use_kerberos
) {
3206 cli
->fallback_after_kerberos
= true;
3208 if (flags
& CLI_FULL_CONNECTION_USE_CCACHE
) {
3209 cli
->use_ccache
= true;
3212 nt_status
= cli_negprot(cli
);
3213 if (!NT_STATUS_IS_OK(nt_status
)) {
3214 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status
)));
3220 return NT_STATUS_OK
;
3225 establishes a connection right up to doing tconX, password specified.
3226 @param output_cli A fully initialised cli structure, non-null only on success
3227 @param dest_host The netbios name of the remote host
3228 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3229 @param port (optional) The destination port (0 for default)
3230 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3231 @param service_type The 'type' of serivice.
3232 @param user Username, unix string
3233 @param domain User's domain
3234 @param password User's password, unencrypted unix string.
3237 NTSTATUS
cli_full_connection(struct cli_state
**output_cli
,
3238 const char *my_name
,
3239 const char *dest_host
,
3240 struct sockaddr_storage
*dest_ss
, int port
,
3241 const char *service
, const char *service_type
,
3242 const char *user
, const char *domain
,
3243 const char *password
, int flags
,
3247 struct cli_state
*cli
= NULL
;
3248 int pw_len
= password
? strlen(password
)+1 : 0;
3252 if (password
== NULL
) {
3256 nt_status
= cli_start_connection(&cli
, my_name
, dest_host
,
3257 dest_ss
, port
, signing_state
,
3260 if (!NT_STATUS_IS_OK(nt_status
)) {
3264 cli
->use_oplocks
= ((flags
& CLI_FULL_CONNECTION_OPLOCKS
) != 0);
3265 cli
->use_level_II_oplocks
=
3266 ((flags
& CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS
) != 0);
3268 nt_status
= cli_session_setup(cli
, user
, password
, pw_len
, password
,
3270 if (!NT_STATUS_IS_OK(nt_status
)) {
3272 if (!(flags
& CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK
)) {
3273 DEBUG(1,("failed session setup with %s\n",
3274 nt_errstr(nt_status
)));
3279 nt_status
= cli_session_setup(cli
, "", "", 0, "", 0, domain
);
3280 if (!NT_STATUS_IS_OK(nt_status
)) {
3281 DEBUG(1,("anonymous failed session setup with %s\n",
3282 nt_errstr(nt_status
)));
3289 nt_status
= cli_tcon_andx(cli
, service
, service_type
, password
,
3291 if (!NT_STATUS_IS_OK(nt_status
)) {
3292 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status
)));
3294 if (NT_STATUS_IS_OK(nt_status
)) {
3295 nt_status
= NT_STATUS_UNSUCCESSFUL
;
3301 nt_status
= cli_init_creds(cli
, user
, domain
, password
);
3302 if (!NT_STATUS_IS_OK(nt_status
)) {
3308 return NT_STATUS_OK
;
3311 /****************************************************************************
3312 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
3313 ****************************************************************************/
3315 bool attempt_netbios_session_request(struct cli_state
**ppcli
, const char *srchost
, const char *desthost
,
3316 struct sockaddr_storage
*pdest_ss
)
3318 struct nmb_name calling
, called
;
3320 make_nmb_name(&calling
, srchost
, 0x0);
3323 * If the called name is an IP address
3324 * then use *SMBSERVER immediately.
3327 if(is_ipaddress(desthost
)) {
3328 make_nmb_name(&called
, STAR_SMBSERVER
, 0x20);
3330 make_nmb_name(&called
, desthost
, 0x20);
3333 if (!cli_session_request(*ppcli
, &calling
, &called
)) {
3335 struct nmb_name smbservername
;
3337 make_nmb_name(&smbservername
, STAR_SMBSERVER
, 0x20);
3340 * If the name wasn't *SMBSERVER then
3341 * try with *SMBSERVER if the first name fails.
3344 if (nmb_name_equal(&called
, &smbservername
)) {
3347 * The name used was *SMBSERVER, don't bother with another name.
3350 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
3351 with error %s.\n", desthost
, cli_errstr(*ppcli
) ));
3356 cli_shutdown(*ppcli
);
3358 *ppcli
= cli_initialise();
3360 /* Out of memory... */
3364 status
= cli_connect(*ppcli
, desthost
, pdest_ss
);
3365 if (!NT_STATUS_IS_OK(status
) ||
3366 !cli_session_request(*ppcli
, &calling
, &smbservername
)) {
3367 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
3368 name *SMBSERVER with error %s\n", desthost
, cli_errstr(*ppcli
) ));
3376 /****************************************************************************
3377 Send an old style tcon.
3378 ****************************************************************************/
3379 NTSTATUS
cli_raw_tcon(struct cli_state
*cli
,
3380 const char *service
, const char *pass
, const char *dev
,
3381 uint16
*max_xmit
, uint16
*tid
)
3383 struct tevent_req
*req
;
3388 if (!lp_client_plaintext_auth() && (*pass
)) {
3389 DEBUG(1, ("Server requested plaintext password but 'client "
3390 "plaintext auth' is disabled\n"));
3391 return NT_STATUS_ACCESS_DENIED
;
3394 bytes
= talloc_array(talloc_tos(), uint8_t, 0);
3395 bytes
= smb_bytes_push_bytes(bytes
, 4, NULL
, 0);
3396 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
3397 service
, strlen(service
)+1, NULL
);
3398 bytes
= smb_bytes_push_bytes(bytes
, 4, NULL
, 0);
3399 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
3400 pass
, strlen(pass
)+1, NULL
);
3401 bytes
= smb_bytes_push_bytes(bytes
, 4, NULL
, 0);
3402 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
3403 dev
, strlen(dev
)+1, NULL
);
3405 status
= cli_smb(talloc_tos(), cli
, SMBtcon
, 0, 0, NULL
,
3406 talloc_get_size(bytes
), bytes
, &req
,
3407 2, NULL
, &ret_vwv
, NULL
, NULL
);
3408 if (!NT_STATUS_IS_OK(status
)) {
3412 *max_xmit
= SVAL(ret_vwv
+ 0, 0);
3413 *tid
= SVAL(ret_vwv
+ 1, 0);
3415 return NT_STATUS_OK
;
3418 /* Return a cli_state pointing at the IPC$ share for the given server */
3420 struct cli_state
*get_ipc_connect(char *server
,
3421 struct sockaddr_storage
*server_ss
,
3422 const struct user_auth_info
*user_info
)
3424 struct cli_state
*cli
;
3426 uint32_t flags
= CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK
;
3428 if (user_info
->use_kerberos
) {
3429 flags
|= CLI_FULL_CONNECTION_USE_KERBEROS
;
3432 nt_status
= cli_full_connection(&cli
, NULL
, server
, server_ss
, 0, "IPC$", "IPC",
3433 user_info
->username
? user_info
->username
: "",
3435 user_info
->password
? user_info
->password
: "",
3439 if (NT_STATUS_IS_OK(nt_status
)) {
3441 } else if (is_ipaddress(server
)) {
3442 /* windows 9* needs a correct NMB name for connections */
3443 fstring remote_name
;
3445 if (name_status_find("*", 0, 0, server_ss
, remote_name
)) {
3446 cli
= get_ipc_connect(remote_name
, server_ss
, user_info
);
3455 * Given the IP address of a master browser on the network, return its
3456 * workgroup and connect to it.
3458 * This function is provided to allow additional processing beyond what
3459 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3460 * browsers and obtain each master browsers' list of domains (in case the
3461 * first master browser is recently on the network and has not yet
3462 * synchronized with other master browsers and therefore does not yet have the
3463 * entire network browse list)
3466 struct cli_state
*get_ipc_connect_master_ip(TALLOC_CTX
*ctx
,
3467 struct sockaddr_storage
*mb_ip
,
3468 const struct user_auth_info
*user_info
,
3469 char **pp_workgroup_out
)
3471 char addr
[INET6_ADDRSTRLEN
];
3473 struct cli_state
*cli
;
3474 struct sockaddr_storage server_ss
;
3476 *pp_workgroup_out
= NULL
;
3478 print_sockaddr(addr
, sizeof(addr
), mb_ip
);
3479 DEBUG(99, ("Looking up name of master browser %s\n",
3483 * Do a name status query to find out the name of the master browser.
3484 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3485 * master browser will not respond to a wildcard query (or, at least,
3486 * an NT4 server acting as the domain master browser will not).
3488 * We might be able to use ONLY the query on MSBROWSE, but that's not
3489 * yet been tested with all Windows versions, so until it is, leave
3490 * the original wildcard query as the first choice and fall back to
3491 * MSBROWSE if the wildcard query fails.
3493 if (!name_status_find("*", 0, 0x1d, mb_ip
, name
) &&
3494 !name_status_find(MSBROWSE
, 1, 0x1d, mb_ip
, name
)) {
3496 DEBUG(99, ("Could not retrieve name status for %s\n",
3501 if (!find_master_ip(name
, &server_ss
)) {
3502 DEBUG(99, ("Could not find master ip for %s\n", name
));
3506 *pp_workgroup_out
= talloc_strdup(ctx
, name
);
3508 DEBUG(4, ("found master browser %s, %s\n", name
, addr
));
3510 print_sockaddr(addr
, sizeof(addr
), &server_ss
);
3511 cli
= get_ipc_connect(addr
, &server_ss
, user_info
);
3517 * Return the IP address and workgroup of a master browser on the network, and
3521 struct cli_state
*get_ipc_connect_master_ip_bcast(TALLOC_CTX
*ctx
,
3522 const struct user_auth_info
*user_info
,
3523 char **pp_workgroup_out
)
3525 struct sockaddr_storage
*ip_list
;
3526 struct cli_state
*cli
;
3530 *pp_workgroup_out
= NULL
;
3532 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3534 /* Go looking for workgroups by broadcasting on the local network */
3536 status
= name_resolve_bcast(MSBROWSE
, 1, talloc_tos(),
3538 if (!NT_STATUS_IS_OK(status
)) {
3539 DEBUG(99, ("No master browsers responded: %s\n",
3540 nt_errstr(status
)));
3544 for (i
= 0; i
< count
; i
++) {
3545 char addr
[INET6_ADDRSTRLEN
];
3546 print_sockaddr(addr
, sizeof(addr
), &ip_list
[i
]);
3547 DEBUG(99, ("Found master browser %s\n", addr
));
3549 cli
= get_ipc_connect_master_ip(ctx
, &ip_list
[i
],
3550 user_info
, pp_workgroup_out
);