2 Unix SMB/CIFS implementation.
3 client connect/disconnect routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Andrew Bartlett 2001-2003
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "popt_common.h"
23 #include "../libcli/auth/libcli_auth.h"
24 #include "../libcli/auth/spnego.h"
26 #include "../libcli/auth/ntlmssp.h"
27 #include "libads/kerberos_proto.h"
29 #include "async_smb.h"
30 #include "libsmb/nmblib.h"
36 {PROTOCOL_CORE
, "PC NETWORK PROGRAM 1.0"},
37 {PROTOCOL_COREPLUS
, "MICROSOFT NETWORKS 1.03"},
38 {PROTOCOL_LANMAN1
, "MICROSOFT NETWORKS 3.0"},
39 {PROTOCOL_LANMAN1
, "LANMAN1.0"},
40 {PROTOCOL_LANMAN2
, "LM1.2X002"},
41 {PROTOCOL_LANMAN2
, "DOS LANMAN2.1"},
42 {PROTOCOL_LANMAN2
, "LANMAN2.1"},
43 {PROTOCOL_LANMAN2
, "Samba"},
44 {PROTOCOL_NT1
, "NT LANMAN 1.0"},
45 {PROTOCOL_NT1
, "NT LM 0.12"},
48 #define STAR_SMBSERVER "*SMBSERVER"
51 * Set the user session key for a connection
52 * @param cli The cli structure to add it too
53 * @param session_key The session key used. (A copy of this is taken for the cli struct)
57 static void cli_set_session_key (struct cli_state
*cli
, const DATA_BLOB session_key
)
59 cli
->user_session_key
= data_blob(session_key
.data
, session_key
.length
);
62 /****************************************************************************
63 Do an old lanman2 style session setup.
64 ****************************************************************************/
66 static NTSTATUS
cli_session_setup_lanman2(struct cli_state
*cli
,
68 const char *pass
, size_t passlen
,
69 const char *workgroup
)
71 DATA_BLOB lm_response
= data_blob_null
;
76 if (passlen
> sizeof(pword
)-1) {
77 return NT_STATUS_INVALID_PARAMETER
;
80 /* LANMAN servers predate NT status codes and Unicode and ignore those
81 smb flags so we must disable the corresponding default capabilities
82 that would otherwise cause the Unicode and NT Status flags to be
83 set (and even returned by the server) */
85 cli
->capabilities
&= ~(CAP_UNICODE
| CAP_STATUS32
);
87 /* if in share level security then don't send a password now */
88 if (!(cli
->sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
))
91 if (passlen
> 0 && (cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) && passlen
!= 24) {
92 /* Encrypted mode needed, and non encrypted password supplied. */
93 lm_response
= data_blob(NULL
, 24);
94 if (!SMBencrypt(pass
, cli
->secblob
.data
,(uchar
*)lm_response
.data
)) {
95 DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
96 return NT_STATUS_ACCESS_DENIED
;
98 } else if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) && passlen
== 24) {
99 /* Encrypted mode needed, and encrypted password supplied. */
100 lm_response
= data_blob(pass
, passlen
);
101 } else if (passlen
> 0) {
102 /* Plaintext mode needed, assume plaintext supplied. */
103 passlen
= clistr_push(cli
, pword
, pass
, sizeof(pword
), STR_TERMINATE
);
104 lm_response
= data_blob(pass
, passlen
);
107 /* send a session setup command */
108 memset(cli
->outbuf
,'\0',smb_size
);
109 cli_set_message(cli
->outbuf
,10, 0, True
);
110 SCVAL(cli
->outbuf
,smb_com
,SMBsesssetupX
);
111 cli_setup_packet(cli
);
113 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
114 SSVAL(cli
->outbuf
,smb_vwv2
,cli
->max_xmit
);
115 SSVAL(cli
->outbuf
,smb_vwv3
,2);
116 SSVAL(cli
->outbuf
,smb_vwv4
,1);
117 SIVAL(cli
->outbuf
,smb_vwv5
,cli
->sesskey
);
118 SSVAL(cli
->outbuf
,smb_vwv7
,lm_response
.length
);
120 p
= smb_buf(cli
->outbuf
);
121 memcpy(p
,lm_response
.data
,lm_response
.length
);
122 p
+= lm_response
.length
;
123 p
+= clistr_push(cli
, p
, user
, -1, STR_TERMINATE
|STR_UPPER
);
124 p
+= clistr_push(cli
, p
, workgroup
, -1, STR_TERMINATE
|STR_UPPER
);
125 p
+= clistr_push(cli
, p
, "Unix", -1, STR_TERMINATE
);
126 p
+= clistr_push(cli
, p
, "Samba", -1, STR_TERMINATE
);
127 cli_setup_bcc(cli
, p
);
129 if (!cli_send_smb(cli
) || !cli_receive_smb(cli
)) {
130 return cli_nt_error(cli
);
133 show_msg(cli
->inbuf
);
135 if (cli_is_error(cli
)) {
136 return cli_nt_error(cli
);
139 /* use the returned vuid from now on */
140 cli
->vuid
= SVAL(cli
->inbuf
,smb_uid
);
141 status
= cli_set_username(cli
, user
);
142 if (!NT_STATUS_IS_OK(status
)) {
148 /****************************************************************************
149 Work out suitable capabilities to offer the server.
150 ****************************************************************************/
152 static uint32
cli_session_setup_capabilities(struct cli_state
*cli
)
154 uint32 capabilities
= CAP_NT_SMBS
;
156 if (!cli
->force_dos_errors
)
157 capabilities
|= CAP_STATUS32
;
159 if (cli
->use_level_II_oplocks
)
160 capabilities
|= CAP_LEVEL_II_OPLOCKS
;
162 capabilities
|= (cli
->capabilities
& (CAP_UNICODE
|CAP_LARGE_FILES
|CAP_LARGE_READX
|CAP_LARGE_WRITEX
|CAP_DFS
));
166 /****************************************************************************
167 Do a NT1 guest session setup.
168 ****************************************************************************/
170 struct cli_session_setup_guest_state
{
171 struct cli_state
*cli
;
176 static void cli_session_setup_guest_done(struct tevent_req
*subreq
);
178 struct tevent_req
*cli_session_setup_guest_create(TALLOC_CTX
*mem_ctx
,
179 struct event_context
*ev
,
180 struct cli_state
*cli
,
181 struct tevent_req
**psmbreq
)
183 struct tevent_req
*req
, *subreq
;
184 struct cli_session_setup_guest_state
*state
;
188 req
= tevent_req_create(mem_ctx
, &state
,
189 struct cli_session_setup_guest_state
);
196 SCVAL(vwv
+0, 0, 0xFF);
199 SSVAL(vwv
+2, 0, CLI_BUFFER_SIZE
);
201 SSVAL(vwv
+4, 0, cli
->pid
);
202 SIVAL(vwv
+5, 0, cli
->sesskey
);
207 SIVAL(vwv
+11, 0, cli_session_setup_capabilities(cli
));
209 bytes
= talloc_array(state
, uint8_t, 0);
211 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "", 1, /* username */
213 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "", 1, /* workgroup */
215 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "Unix", 5, NULL
);
216 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "Samba", 6, NULL
);
223 state
->bytes
.iov_base
= (void *)bytes
;
224 state
->bytes
.iov_len
= talloc_get_size(bytes
);
226 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBsesssetupX
, 0, 13, vwv
,
228 if (subreq
== NULL
) {
232 tevent_req_set_callback(subreq
, cli_session_setup_guest_done
, req
);
237 struct tevent_req
*cli_session_setup_guest_send(TALLOC_CTX
*mem_ctx
,
238 struct event_context
*ev
,
239 struct cli_state
*cli
)
241 struct tevent_req
*req
, *subreq
;
244 req
= cli_session_setup_guest_create(mem_ctx
, ev
, cli
, &subreq
);
249 status
= cli_smb_req_send(subreq
);
250 if (NT_STATUS_IS_OK(status
)) {
251 tevent_req_nterror(req
, status
);
252 return tevent_req_post(req
, ev
);
257 static void cli_session_setup_guest_done(struct tevent_req
*subreq
)
259 struct tevent_req
*req
= tevent_req_callback_data(
260 subreq
, struct tevent_req
);
261 struct cli_session_setup_guest_state
*state
= tevent_req_data(
262 req
, struct cli_session_setup_guest_state
);
263 struct cli_state
*cli
= state
->cli
;
271 status
= cli_smb_recv(subreq
, state
, &in
, 0, NULL
, NULL
,
274 if (!NT_STATUS_IS_OK(status
)) {
275 tevent_req_nterror(req
, status
);
282 cli
->vuid
= SVAL(inbuf
, smb_uid
);
284 p
+= clistr_pull(inbuf
, cli
->server_os
, (char *)p
, sizeof(fstring
),
285 bytes
+num_bytes
-p
, STR_TERMINATE
);
286 p
+= clistr_pull(inbuf
, cli
->server_type
, (char *)p
, sizeof(fstring
),
287 bytes
+num_bytes
-p
, STR_TERMINATE
);
288 p
+= clistr_pull(inbuf
, cli
->server_domain
, (char *)p
, sizeof(fstring
),
289 bytes
+num_bytes
-p
, STR_TERMINATE
);
291 if (strstr(cli
->server_type
, "Samba")) {
292 cli
->is_samba
= True
;
295 status
= cli_set_username(cli
, "");
296 if (!NT_STATUS_IS_OK(status
)) {
297 tevent_req_nterror(req
, status
);
300 tevent_req_done(req
);
303 NTSTATUS
cli_session_setup_guest_recv(struct tevent_req
*req
)
305 return tevent_req_simple_recv_ntstatus(req
);
308 static NTSTATUS
cli_session_setup_guest(struct cli_state
*cli
)
310 TALLOC_CTX
*frame
= talloc_stackframe();
311 struct event_context
*ev
;
312 struct tevent_req
*req
;
313 NTSTATUS status
= NT_STATUS_OK
;
315 if (cli_has_async_calls(cli
)) {
317 * Can't use sync call while an async call is in flight
319 status
= NT_STATUS_INVALID_PARAMETER
;
323 ev
= event_context_init(frame
);
325 status
= NT_STATUS_NO_MEMORY
;
329 req
= cli_session_setup_guest_send(frame
, ev
, cli
);
331 status
= NT_STATUS_NO_MEMORY
;
335 if (!tevent_req_poll(req
, ev
)) {
336 status
= map_nt_error_from_unix(errno
);
340 status
= cli_session_setup_guest_recv(req
);
343 if (!NT_STATUS_IS_OK(status
)) {
344 cli_set_error(cli
, status
);
349 /****************************************************************************
350 Do a NT1 plaintext session setup.
351 ****************************************************************************/
353 static NTSTATUS
cli_session_setup_plaintext(struct cli_state
*cli
,
354 const char *user
, const char *pass
,
355 const char *workgroup
)
357 uint32 capabilities
= cli_session_setup_capabilities(cli
);
362 fstr_sprintf( lanman
, "Samba %s", samba_version_string());
364 memset(cli
->outbuf
, '\0', smb_size
);
365 cli_set_message(cli
->outbuf
,13,0,True
);
366 SCVAL(cli
->outbuf
,smb_com
,SMBsesssetupX
);
367 cli_setup_packet(cli
);
369 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
370 SSVAL(cli
->outbuf
,smb_vwv2
,CLI_BUFFER_SIZE
);
371 SSVAL(cli
->outbuf
,smb_vwv3
,2);
372 SSVAL(cli
->outbuf
,smb_vwv4
,cli
->pid
);
373 SIVAL(cli
->outbuf
,smb_vwv5
,cli
->sesskey
);
374 SSVAL(cli
->outbuf
,smb_vwv8
,0);
375 SIVAL(cli
->outbuf
,smb_vwv11
,capabilities
);
376 p
= smb_buf(cli
->outbuf
);
378 /* check wether to send the ASCII or UNICODE version of the password */
380 if ( (capabilities
& CAP_UNICODE
) == 0 ) {
381 p
+= clistr_push(cli
, p
, pass
, -1, STR_TERMINATE
); /* password */
382 SSVAL(cli
->outbuf
,smb_vwv7
,PTR_DIFF(p
, smb_buf(cli
->outbuf
)));
385 /* For ucs2 passwords clistr_push calls ucs2_align, which causes
386 * the space taken by the unicode password to be one byte too
387 * long (as we're on an odd byte boundary here). Reduce the
388 * count by 1 to cope with this. Fixes smbclient against NetApp
389 * servers which can't cope. Fix from
390 * bryan.kolodziej@allenlund.com in bug #3840.
392 p
+= clistr_push(cli
, p
, pass
, -1, STR_UNICODE
|STR_TERMINATE
); /* unicode password */
393 SSVAL(cli
->outbuf
,smb_vwv8
,PTR_DIFF(p
, smb_buf(cli
->outbuf
))-1);
396 p
+= clistr_push(cli
, p
, user
, -1, STR_TERMINATE
); /* username */
397 p
+= clistr_push(cli
, p
, workgroup
, -1, STR_TERMINATE
); /* workgroup */
398 p
+= clistr_push(cli
, p
, "Unix", -1, STR_TERMINATE
);
399 p
+= clistr_push(cli
, p
, lanman
, -1, STR_TERMINATE
);
400 cli_setup_bcc(cli
, p
);
402 if (!cli_send_smb(cli
) || !cli_receive_smb(cli
)) {
403 return cli_nt_error(cli
);
406 show_msg(cli
->inbuf
);
408 if (cli_is_error(cli
)) {
409 return cli_nt_error(cli
);
412 cli
->vuid
= SVAL(cli
->inbuf
,smb_uid
);
413 p
= smb_buf(cli
->inbuf
);
414 p
+= clistr_pull(cli
->inbuf
, cli
->server_os
, p
, sizeof(fstring
),
416 p
+= clistr_pull(cli
->inbuf
, cli
->server_type
, p
, sizeof(fstring
),
418 p
+= clistr_pull(cli
->inbuf
, cli
->server_domain
, p
, sizeof(fstring
),
420 status
= cli_set_username(cli
, user
);
421 if (!NT_STATUS_IS_OK(status
)) {
424 if (strstr(cli
->server_type
, "Samba")) {
425 cli
->is_samba
= True
;
431 /****************************************************************************
432 do a NT1 NTLM/LM encrypted session setup - for when extended security
434 @param cli client state to create do session setup on
436 @param pass *either* cleartext password (passlen !=24) or LM response.
437 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
438 @param workgroup The user's domain.
439 ****************************************************************************/
441 static NTSTATUS
cli_session_setup_nt1(struct cli_state
*cli
, const char *user
,
442 const char *pass
, size_t passlen
,
443 const char *ntpass
, size_t ntpasslen
,
444 const char *workgroup
)
446 uint32 capabilities
= cli_session_setup_capabilities(cli
);
447 DATA_BLOB lm_response
= data_blob_null
;
448 DATA_BLOB nt_response
= data_blob_null
;
449 DATA_BLOB session_key
= data_blob_null
;
455 /* do nothing - guest login */
456 } else if (passlen
!= 24) {
457 if (lp_client_ntlmv2_auth()) {
458 DATA_BLOB server_chal
;
459 DATA_BLOB names_blob
;
460 server_chal
= data_blob(cli
->secblob
.data
, MIN(cli
->secblob
.length
, 8));
462 /* note that the 'workgroup' here is a best guess - we don't know
463 the server's domain at this point. The 'server name' is also
466 names_blob
= NTLMv2_generate_names_blob(NULL
, cli
->called
.name
, workgroup
);
468 if (!SMBNTLMv2encrypt(NULL
, user
, workgroup
, pass
, &server_chal
,
470 &lm_response
, &nt_response
, NULL
, &session_key
)) {
471 data_blob_free(&names_blob
);
472 data_blob_free(&server_chal
);
473 return NT_STATUS_ACCESS_DENIED
;
475 data_blob_free(&names_blob
);
476 data_blob_free(&server_chal
);
480 E_md4hash(pass
, nt_hash
);
483 nt_response
= data_blob_null
;
485 nt_response
= data_blob(NULL
, 24);
486 SMBNTencrypt(pass
,cli
->secblob
.data
,nt_response
.data
);
488 /* non encrypted password supplied. Ignore ntpass. */
489 if (lp_client_lanman_auth()) {
490 lm_response
= data_blob(NULL
, 24);
491 if (!SMBencrypt(pass
,cli
->secblob
.data
, lm_response
.data
)) {
492 /* Oops, the LM response is invalid, just put
493 the NT response there instead */
494 data_blob_free(&lm_response
);
495 lm_response
= data_blob(nt_response
.data
, nt_response
.length
);
498 /* LM disabled, place NT# in LM field instead */
499 lm_response
= data_blob(nt_response
.data
, nt_response
.length
);
502 session_key
= data_blob(NULL
, 16);
504 E_deshash(pass
, session_key
.data
);
505 memset(&session_key
.data
[8], '\0', 8);
507 SMBsesskeygen_ntv1(nt_hash
, session_key
.data
);
510 cli_temp_set_signing(cli
);
512 /* pre-encrypted password supplied. Only used for
513 security=server, can't do
514 signing because we don't have original key */
516 lm_response
= data_blob(pass
, passlen
);
517 nt_response
= data_blob(ntpass
, ntpasslen
);
520 /* send a session setup command */
521 memset(cli
->outbuf
,'\0',smb_size
);
523 cli_set_message(cli
->outbuf
,13,0,True
);
524 SCVAL(cli
->outbuf
,smb_com
,SMBsesssetupX
);
525 cli_setup_packet(cli
);
527 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
528 SSVAL(cli
->outbuf
,smb_vwv2
,CLI_BUFFER_SIZE
);
529 SSVAL(cli
->outbuf
,smb_vwv3
,2);
530 SSVAL(cli
->outbuf
,smb_vwv4
,cli
->pid
);
531 SIVAL(cli
->outbuf
,smb_vwv5
,cli
->sesskey
);
532 SSVAL(cli
->outbuf
,smb_vwv7
,lm_response
.length
);
533 SSVAL(cli
->outbuf
,smb_vwv8
,nt_response
.length
);
534 SIVAL(cli
->outbuf
,smb_vwv11
,capabilities
);
535 p
= smb_buf(cli
->outbuf
);
536 if (lm_response
.length
) {
537 memcpy(p
,lm_response
.data
, lm_response
.length
); p
+= lm_response
.length
;
539 if (nt_response
.length
) {
540 memcpy(p
,nt_response
.data
, nt_response
.length
); p
+= nt_response
.length
;
542 p
+= clistr_push(cli
, p
, user
, -1, STR_TERMINATE
);
544 /* Upper case here might help some NTLMv2 implementations */
545 p
+= clistr_push(cli
, p
, workgroup
, -1, STR_TERMINATE
|STR_UPPER
);
546 p
+= clistr_push(cli
, p
, "Unix", -1, STR_TERMINATE
);
547 p
+= clistr_push(cli
, p
, "Samba", -1, STR_TERMINATE
);
548 cli_setup_bcc(cli
, p
);
550 if (!cli_send_smb(cli
) || !cli_receive_smb(cli
)) {
551 result
= cli_nt_error(cli
);
555 /* show_msg(cli->inbuf); */
557 if (cli_is_error(cli
)) {
558 result
= cli_nt_error(cli
);
563 ok
= cli_simple_set_signing(cli
, session_key
, lm_response
);
565 ok
= cli_simple_set_signing(cli
, session_key
, nt_response
);
568 if (!cli_check_sign_mac(cli
, cli
->inbuf
, 1)) {
569 result
= NT_STATUS_ACCESS_DENIED
;
574 /* use the returned vuid from now on */
575 cli
->vuid
= SVAL(cli
->inbuf
,smb_uid
);
577 p
= smb_buf(cli
->inbuf
);
578 p
+= clistr_pull(cli
->inbuf
, cli
->server_os
, p
, sizeof(fstring
),
580 p
+= clistr_pull(cli
->inbuf
, cli
->server_type
, p
, sizeof(fstring
),
582 p
+= clistr_pull(cli
->inbuf
, cli
->server_domain
, p
, sizeof(fstring
),
585 if (strstr(cli
->server_type
, "Samba")) {
586 cli
->is_samba
= True
;
589 result
= cli_set_username(cli
, user
);
590 if (!NT_STATUS_IS_OK(result
)) {
594 if (session_key
.data
) {
595 /* Have plaintext orginal */
596 cli_set_session_key(cli
, session_key
);
599 result
= NT_STATUS_OK
;
601 data_blob_free(&lm_response
);
602 data_blob_free(&nt_response
);
603 data_blob_free(&session_key
);
607 /* The following is calculated from :
609 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
610 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
614 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
616 struct cli_sesssetup_blob_state
{
617 struct tevent_context
*ev
;
618 struct cli_state
*cli
;
620 uint16_t max_blob_size
;
629 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state
*state
,
630 struct tevent_req
**psubreq
);
631 static void cli_sesssetup_blob_done(struct tevent_req
*subreq
);
633 static struct tevent_req
*cli_sesssetup_blob_send(TALLOC_CTX
*mem_ctx
,
634 struct tevent_context
*ev
,
635 struct cli_state
*cli
,
638 struct tevent_req
*req
, *subreq
;
639 struct cli_sesssetup_blob_state
*state
;
641 req
= tevent_req_create(mem_ctx
, &state
,
642 struct cli_sesssetup_blob_state
);
650 if (cli
->max_xmit
< BASE_SESSSETUP_BLOB_PACKET_SIZE
+ 1) {
651 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
652 "(was %u, need minimum %u)\n",
653 (unsigned int)cli
->max_xmit
,
654 BASE_SESSSETUP_BLOB_PACKET_SIZE
));
655 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
656 return tevent_req_post(req
, ev
);
658 state
->max_blob_size
=
659 MIN(cli
->max_xmit
- BASE_SESSSETUP_BLOB_PACKET_SIZE
, 0xFFFF);
661 if (!cli_sesssetup_blob_next(state
, &subreq
)) {
662 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
663 return tevent_req_post(req
, ev
);
665 tevent_req_set_callback(subreq
, cli_sesssetup_blob_done
, req
);
669 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state
*state
,
670 struct tevent_req
**psubreq
)
672 struct tevent_req
*subreq
;
675 SCVAL(state
->vwv
+0, 0, 0xFF);
676 SCVAL(state
->vwv
+0, 1, 0);
677 SSVAL(state
->vwv
+1, 0, 0);
678 SSVAL(state
->vwv
+2, 0, CLI_BUFFER_SIZE
);
679 SSVAL(state
->vwv
+3, 0, 2);
680 SSVAL(state
->vwv
+4, 0, 1);
681 SIVAL(state
->vwv
+5, 0, 0);
683 thistime
= MIN(state
->blob
.length
, state
->max_blob_size
);
684 SSVAL(state
->vwv
+7, 0, thistime
);
686 SSVAL(state
->vwv
+8, 0, 0);
687 SSVAL(state
->vwv
+9, 0, 0);
688 SIVAL(state
->vwv
+10, 0,
689 cli_session_setup_capabilities(state
->cli
)
690 | CAP_EXTENDED_SECURITY
);
692 state
->buf
= (uint8_t *)talloc_memdup(state
, state
->blob
.data
,
694 if (state
->buf
== NULL
) {
697 state
->blob
.data
+= thistime
;
698 state
->blob
.length
-= thistime
;
700 state
->buf
= smb_bytes_push_str(state
->buf
, cli_ucs2(state
->cli
),
702 state
->buf
= smb_bytes_push_str(state
->buf
, cli_ucs2(state
->cli
),
704 if (state
->buf
== NULL
) {
707 subreq
= cli_smb_send(state
, state
->ev
, state
->cli
, SMBsesssetupX
, 0,
709 talloc_get_size(state
->buf
), state
->buf
);
710 if (subreq
== NULL
) {
717 static void cli_sesssetup_blob_done(struct tevent_req
*subreq
)
719 struct tevent_req
*req
= tevent_req_callback_data(
720 subreq
, struct tevent_req
);
721 struct cli_sesssetup_blob_state
*state
= tevent_req_data(
722 req
, struct cli_sesssetup_blob_state
);
723 struct cli_state
*cli
= state
->cli
;
730 uint16_t blob_length
;
733 status
= cli_smb_recv(subreq
, state
, &inbuf
, 1, &wct
, &vwv
,
736 if (!NT_STATUS_IS_OK(status
)
737 && !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
738 tevent_req_nterror(req
, status
);
742 state
->status
= status
;
743 TALLOC_FREE(state
->buf
);
745 state
->inbuf
= (char *)inbuf
;
746 cli
->vuid
= SVAL(state
->inbuf
, smb_uid
);
748 blob_length
= SVAL(vwv
+3, 0);
749 if (blob_length
> num_bytes
) {
750 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
753 state
->ret_blob
= data_blob_const(bytes
, blob_length
);
755 p
= bytes
+ blob_length
;
757 p
+= clistr_pull(state
->inbuf
, cli
->server_os
,
758 (char *)p
, sizeof(fstring
),
759 bytes
+num_bytes
-p
, STR_TERMINATE
);
760 p
+= clistr_pull(state
->inbuf
, cli
->server_type
,
761 (char *)p
, sizeof(fstring
),
762 bytes
+num_bytes
-p
, STR_TERMINATE
);
763 p
+= clistr_pull(state
->inbuf
, cli
->server_domain
,
764 (char *)p
, sizeof(fstring
),
765 bytes
+num_bytes
-p
, STR_TERMINATE
);
767 if (strstr(cli
->server_type
, "Samba")) {
768 cli
->is_samba
= True
;
771 if (state
->blob
.length
!= 0) {
775 if (!cli_sesssetup_blob_next(state
, &subreq
)) {
776 tevent_req_nomem(NULL
, req
);
779 tevent_req_set_callback(subreq
, cli_sesssetup_blob_done
, req
);
782 tevent_req_done(req
);
785 static NTSTATUS
cli_sesssetup_blob_recv(struct tevent_req
*req
,
790 struct cli_sesssetup_blob_state
*state
= tevent_req_data(
791 req
, struct cli_sesssetup_blob_state
);
795 if (tevent_req_is_nterror(req
, &status
)) {
796 state
->cli
->vuid
= 0;
800 inbuf
= talloc_move(mem_ctx
, &state
->inbuf
);
802 *pblob
= state
->ret_blob
;
804 if (pinbuf
!= NULL
) {
807 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
808 return state
->status
;
813 /****************************************************************************
814 Use in-memory credentials cache
815 ****************************************************************************/
817 static void use_in_memory_ccache(void) {
818 setenv(KRB5_ENV_CCNAME
, "MEMORY:cliconnect", 1);
821 /****************************************************************************
822 Do a spnego/kerberos encrypted session setup.
823 ****************************************************************************/
825 struct cli_session_setup_kerberos_state
{
826 struct cli_state
*cli
;
827 DATA_BLOB negTokenTarg
;
828 DATA_BLOB session_key_krb5
;
829 ADS_STATUS ads_status
;
832 static void cli_session_setup_kerberos_done(struct tevent_req
*subreq
);
834 static struct tevent_req
*cli_session_setup_kerberos_send(
835 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
, struct cli_state
*cli
,
836 const char *principal
, const char *workgroup
)
838 struct tevent_req
*req
, *subreq
;
839 struct cli_session_setup_kerberos_state
*state
;
842 DEBUG(2,("Doing kerberos session setup\n"));
844 req
= tevent_req_create(mem_ctx
, &state
,
845 struct cli_session_setup_kerberos_state
);
850 state
->ads_status
= ADS_SUCCESS
;
852 cli_temp_set_signing(cli
);
855 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
856 * we have to acquire a ticket. To be fixed later :-)
858 rc
= spnego_gen_krb5_negTokenInit(state
, principal
, 0, &state
->negTokenTarg
,
859 &state
->session_key_krb5
, 0, NULL
);
861 DEBUG(1, ("cli_session_setup_kerberos: "
862 "spnego_gen_krb5_negTokenInit failed: %s\n",
864 state
->ads_status
= ADS_ERROR_KRB5(rc
);
865 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
866 return tevent_req_post(req
, ev
);
870 file_save("negTokenTarg.dat", state
->negTokenTarg
.data
,
871 state
->negTokenTarg
.length
);
874 subreq
= cli_sesssetup_blob_send(state
, ev
, cli
, state
->negTokenTarg
);
875 if (tevent_req_nomem(subreq
, req
)) {
876 return tevent_req_post(req
, ev
);
878 tevent_req_set_callback(subreq
, cli_session_setup_kerberos_done
, req
);
882 static void cli_session_setup_kerberos_done(struct tevent_req
*subreq
)
884 struct tevent_req
*req
= tevent_req_callback_data(
885 subreq
, struct tevent_req
);
886 struct cli_session_setup_kerberos_state
*state
= tevent_req_data(
887 req
, struct cli_session_setup_kerberos_state
);
891 status
= cli_sesssetup_blob_recv(subreq
, talloc_tos(), NULL
, &inbuf
);
892 if (!NT_STATUS_IS_OK(status
)) {
894 tevent_req_nterror(req
, status
);
898 cli_set_session_key(state
->cli
, state
->session_key_krb5
);
900 if (cli_simple_set_signing(state
->cli
, state
->session_key_krb5
,
902 && !cli_check_sign_mac(state
->cli
, inbuf
, 1)) {
904 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
908 tevent_req_done(req
);
911 static ADS_STATUS
cli_session_setup_kerberos_recv(struct tevent_req
*req
)
913 struct cli_session_setup_kerberos_state
*state
= tevent_req_data(
914 req
, struct cli_session_setup_kerberos_state
);
917 if (tevent_req_is_nterror(req
, &status
)) {
918 return ADS_ERROR_NT(status
);
920 return state
->ads_status
;
923 static ADS_STATUS
cli_session_setup_kerberos(struct cli_state
*cli
,
924 const char *principal
,
925 const char *workgroup
)
927 struct tevent_context
*ev
;
928 struct tevent_req
*req
;
929 ADS_STATUS status
= ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
931 if (cli_has_async_calls(cli
)) {
932 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
934 ev
= tevent_context_init(talloc_tos());
938 req
= cli_session_setup_kerberos_send(ev
, ev
, cli
, principal
,
943 if (!tevent_req_poll(req
, ev
)) {
944 status
= ADS_ERROR_SYSTEM(errno
);
947 status
= cli_session_setup_kerberos_recv(req
);
952 #endif /* HAVE_KRB5 */
954 /****************************************************************************
955 Do a spnego/NTLMSSP encrypted session setup.
956 ****************************************************************************/
958 struct cli_session_setup_ntlmssp_state
{
959 struct tevent_context
*ev
;
960 struct cli_state
*cli
;
961 struct ntlmssp_state
*ntlmssp_state
;
966 static int cli_session_setup_ntlmssp_state_destructor(
967 struct cli_session_setup_ntlmssp_state
*state
)
969 if (state
->ntlmssp_state
!= NULL
) {
970 TALLOC_FREE(state
->ntlmssp_state
);
975 static void cli_session_setup_ntlmssp_done(struct tevent_req
*req
);
977 static struct tevent_req
*cli_session_setup_ntlmssp_send(
978 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
, struct cli_state
*cli
,
979 const char *user
, const char *pass
, const char *domain
)
981 struct tevent_req
*req
, *subreq
;
982 struct cli_session_setup_ntlmssp_state
*state
;
985 const char *OIDs_ntlm
[] = {OID_NTLMSSP
, NULL
};
987 req
= tevent_req_create(mem_ctx
, &state
,
988 struct cli_session_setup_ntlmssp_state
);
996 state
->ntlmssp_state
= NULL
;
997 talloc_set_destructor(
998 state
, cli_session_setup_ntlmssp_state_destructor
);
1000 cli_temp_set_signing(cli
);
1002 status
= ntlmssp_client_start(state
,
1005 lp_client_ntlmv2_auth(),
1006 &state
->ntlmssp_state
);
1007 if (!NT_STATUS_IS_OK(status
)) {
1010 ntlmssp_want_feature(state
->ntlmssp_state
,
1011 NTLMSSP_FEATURE_SESSION_KEY
);
1012 if (cli
->use_ccache
) {
1013 ntlmssp_want_feature(state
->ntlmssp_state
,
1014 NTLMSSP_FEATURE_CCACHE
);
1016 status
= ntlmssp_set_username(state
->ntlmssp_state
, user
);
1017 if (!NT_STATUS_IS_OK(status
)) {
1020 status
= ntlmssp_set_domain(state
->ntlmssp_state
, domain
);
1021 if (!NT_STATUS_IS_OK(status
)) {
1024 status
= ntlmssp_set_password(state
->ntlmssp_state
, pass
);
1025 if (!NT_STATUS_IS_OK(status
)) {
1028 status
= ntlmssp_update(state
->ntlmssp_state
, data_blob_null
,
1030 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1034 state
->blob_out
= spnego_gen_negTokenInit(state
, OIDs_ntlm
, &blob_out
, NULL
);
1035 data_blob_free(&blob_out
);
1037 subreq
= cli_sesssetup_blob_send(state
, ev
, cli
, state
->blob_out
);
1038 if (tevent_req_nomem(subreq
, req
)) {
1039 return tevent_req_post(req
, ev
);
1041 tevent_req_set_callback(subreq
, cli_session_setup_ntlmssp_done
, req
);
1044 tevent_req_nterror(req
, status
);
1045 return tevent_req_post(req
, ev
);
1048 static void cli_session_setup_ntlmssp_done(struct tevent_req
*subreq
)
1050 struct tevent_req
*req
= tevent_req_callback_data(
1051 subreq
, struct tevent_req
);
1052 struct cli_session_setup_ntlmssp_state
*state
= tevent_req_data(
1053 req
, struct cli_session_setup_ntlmssp_state
);
1054 DATA_BLOB blob_in
, msg_in
, blob_out
;
1059 status
= cli_sesssetup_blob_recv(subreq
, talloc_tos(), &blob_in
,
1061 TALLOC_FREE(subreq
);
1062 data_blob_free(&state
->blob_out
);
1064 if (NT_STATUS_IS_OK(status
)) {
1065 if (state
->cli
->server_domain
[0] == '\0') {
1066 fstrcpy(state
->cli
->server_domain
,
1067 state
->ntlmssp_state
->server
.netbios_domain
);
1069 cli_set_session_key(
1070 state
->cli
, state
->ntlmssp_state
->session_key
);
1072 if (cli_simple_set_signing(
1073 state
->cli
, state
->ntlmssp_state
->session_key
,
1075 && !cli_check_sign_mac(state
->cli
, inbuf
, 1)) {
1076 TALLOC_FREE(subreq
);
1077 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1080 TALLOC_FREE(subreq
);
1081 TALLOC_FREE(state
->ntlmssp_state
);
1082 tevent_req_done(req
);
1085 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1086 tevent_req_nterror(req
, status
);
1090 if (blob_in
.length
== 0) {
1091 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
1095 if ((state
->turn
== 1)
1096 && NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1097 DATA_BLOB tmp_blob
= data_blob_null
;
1098 /* the server might give us back two challenges */
1099 parse_ret
= spnego_parse_challenge(state
, blob_in
, &msg_in
,
1101 data_blob_free(&tmp_blob
);
1103 parse_ret
= spnego_parse_auth_response(state
, blob_in
, status
,
1104 OID_NTLMSSP
, &msg_in
);
1109 DEBUG(3,("Failed to parse auth response\n"));
1110 if (NT_STATUS_IS_OK(status
)
1111 || NT_STATUS_EQUAL(status
,
1112 NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1114 req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
1119 status
= ntlmssp_update(state
->ntlmssp_state
, msg_in
, &blob_out
);
1121 if (!NT_STATUS_IS_OK(status
)
1122 && !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1123 TALLOC_FREE(subreq
);
1124 TALLOC_FREE(state
->ntlmssp_state
);
1125 tevent_req_nterror(req
, status
);
1129 state
->blob_out
= spnego_gen_auth(state
, blob_out
);
1130 TALLOC_FREE(subreq
);
1131 if (tevent_req_nomem(state
->blob_out
.data
, req
)) {
1135 subreq
= cli_sesssetup_blob_send(state
, state
->ev
, state
->cli
,
1137 if (tevent_req_nomem(subreq
, req
)) {
1140 tevent_req_set_callback(subreq
, cli_session_setup_ntlmssp_done
, req
);
1143 static NTSTATUS
cli_session_setup_ntlmssp_recv(struct tevent_req
*req
)
1145 struct cli_session_setup_ntlmssp_state
*state
= tevent_req_data(
1146 req
, struct cli_session_setup_ntlmssp_state
);
1149 if (tevent_req_is_nterror(req
, &status
)) {
1150 state
->cli
->vuid
= 0;
1153 return NT_STATUS_OK
;
1156 static NTSTATUS
cli_session_setup_ntlmssp(struct cli_state
*cli
,
1161 struct tevent_context
*ev
;
1162 struct tevent_req
*req
;
1163 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1165 if (cli_has_async_calls(cli
)) {
1166 return NT_STATUS_INVALID_PARAMETER
;
1168 ev
= tevent_context_init(talloc_tos());
1172 req
= cli_session_setup_ntlmssp_send(ev
, ev
, cli
, user
, pass
, domain
);
1176 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1179 status
= cli_session_setup_ntlmssp_recv(req
);
1182 if (!NT_STATUS_IS_OK(status
)) {
1183 cli_set_error(cli
, status
);
1188 /****************************************************************************
1189 Do a spnego encrypted session setup.
1191 user_domain: The shortname of the domain the user/machine is a member of.
1192 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1193 ****************************************************************************/
1195 ADS_STATUS
cli_session_setup_spnego(struct cli_state
*cli
, const char *user
,
1196 const char *pass
, const char *user_domain
,
1197 const char * dest_realm
)
1199 char *principal
= NULL
;
1200 char *OIDs
[ASN1_MAX_OIDS
];
1203 const char *p
= NULL
;
1204 char *account
= NULL
;
1207 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli
->secblob
.length
));
1209 /* the server might not even do spnego */
1210 if (cli
->secblob
.length
<= 16) {
1211 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1216 file_save("negprot.dat", cli
->secblob
.data
, cli
->secblob
.length
);
1219 /* there is 16 bytes of GUID before the real spnego packet starts */
1220 blob
= data_blob(cli
->secblob
.data
+16, cli
->secblob
.length
-16);
1222 /* The server sent us the first part of the SPNEGO exchange in the
1223 * negprot reply. It is WRONG to depend on the principal sent in the
1224 * negprot reply, but right now we do it. If we don't receive one,
1225 * we try to best guess, then fall back to NTLM. */
1226 if (!spnego_parse_negTokenInit(talloc_tos(), blob
, OIDs
, &principal
, NULL
) ||
1228 data_blob_free(&blob
);
1229 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
1231 data_blob_free(&blob
);
1233 /* make sure the server understands kerberos */
1234 for (i
=0;OIDs
[i
];i
++) {
1236 DEBUG(3,("got OID=%s\n", OIDs
[i
]));
1238 DEBUGADD(3,("got OID=%s\n", OIDs
[i
]));
1239 if (strcmp(OIDs
[i
], OID_KERBEROS5_OLD
) == 0 ||
1240 strcmp(OIDs
[i
], OID_KERBEROS5
) == 0) {
1241 cli
->got_kerberos_mechanism
= True
;
1243 talloc_free(OIDs
[i
]);
1246 DEBUG(3,("got principal=%s\n", principal
? principal
: "<null>"));
1248 status
= cli_set_username(cli
, user
);
1249 if (!NT_STATUS_IS_OK(status
)) {
1250 TALLOC_FREE(principal
);
1251 return ADS_ERROR_NT(status
);
1255 /* If password is set we reauthenticate to kerberos server
1256 * and do not store results */
1258 if (cli
->got_kerberos_mechanism
&& cli
->use_kerberos
) {
1261 if (pass
&& *pass
) {
1264 use_in_memory_ccache();
1265 ret
= kerberos_kinit_password(user
, pass
, 0 /* no time correction for now */, NULL
);
1268 TALLOC_FREE(principal
);
1269 DEBUG(0, ("Kinit failed: %s\n", error_message(ret
)));
1270 if (cli
->fallback_after_kerberos
)
1272 return ADS_ERROR_KRB5(ret
);
1276 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1278 if (!lp_client_use_spnego_principal() || strequal(principal
, ADS_IGNORE_PRINCIPAL
)) {
1279 TALLOC_FREE(principal
);
1282 if (principal
== NULL
&&
1283 !is_ipaddress(cli
->desthost
) &&
1284 !strequal(STAR_SMBSERVER
,
1288 DEBUG(3,("cli_session_setup_spnego: using target "
1289 "hostname not SPNEGO principal\n"));
1291 host
= strchr_m(cli
->desthost
, '.');
1293 realm
= SMB_STRDUP(dest_realm
);
1298 realm
= kerberos_get_realm_from_hostname(cli
->desthost
);
1300 /* NetBIOS name - use our realm. */
1301 realm
= kerberos_get_default_realm_from_ccache();
1305 if (realm
&& *realm
) {
1306 principal
= talloc_asprintf(talloc_tos(),
1312 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
1314 DEBUG(3,("cli_session_setup_spnego: guessed "
1315 "server principal=%s\n",
1316 principal
? principal
: "<null>"));
1322 rc
= cli_session_setup_kerberos(cli
, principal
,
1324 if (ADS_ERR_OK(rc
) || !cli
->fallback_after_kerberos
) {
1325 TALLOC_FREE(principal
);
1332 TALLOC_FREE(principal
);
1336 account
= talloc_strdup(talloc_tos(), user
);
1338 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
1341 /* when falling back to ntlmssp while authenticating with a machine
1342 * account strip off the realm - gd */
1344 if ((p
= strchr_m(user
, '@')) != NULL
) {
1345 account
[PTR_DIFF(p
,user
)] = '\0';
1348 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli
, account
, pass
, user_domain
));
1351 /****************************************************************************
1352 Send a session setup. The username and workgroup is in UNIX character
1353 format and must be converted to DOS codepage format before sending. If the
1354 password is in plaintext, the same should be done.
1355 ****************************************************************************/
1357 NTSTATUS
cli_session_setup(struct cli_state
*cli
,
1359 const char *pass
, int passlen
,
1360 const char *ntpass
, int ntpasslen
,
1361 const char *workgroup
)
1367 fstrcpy(user2
, user
);
1376 /* allow for workgroups as part of the username */
1377 if ((p
=strchr_m(user2
,'\\')) || (p
=strchr_m(user2
,'/')) ||
1378 (p
=strchr_m(user2
,*lp_winbind_separator()))) {
1384 if (cli
->protocol
< PROTOCOL_LANMAN1
) {
1385 return NT_STATUS_OK
;
1388 /* now work out what sort of session setup we are going to
1389 do. I have split this into separate functions to make the
1390 flow a bit easier to understand (tridge) */
1392 /* if its an older server then we have to use the older request format */
1394 if (cli
->protocol
< PROTOCOL_NT1
) {
1395 if (!lp_client_lanman_auth() && passlen
!= 24 && (*pass
)) {
1396 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
1397 " or 'client ntlmv2 auth = yes'\n"));
1398 return NT_STATUS_ACCESS_DENIED
;
1401 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) == 0 &&
1402 !lp_client_plaintext_auth() && (*pass
)) {
1403 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
1404 " or 'client ntlmv2 auth = yes'\n"));
1405 return NT_STATUS_ACCESS_DENIED
;
1408 return cli_session_setup_lanman2(cli
, user
, pass
, passlen
,
1412 /* if no user is supplied then we have to do an anonymous connection.
1413 passwords are ignored */
1415 if (!user
|| !*user
)
1416 return cli_session_setup_guest(cli
);
1418 /* if the server is share level then send a plaintext null
1419 password at this point. The password is sent in the tree
1422 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
) == 0)
1423 return cli_session_setup_plaintext(cli
, user
, "", workgroup
);
1425 /* if the server doesn't support encryption then we have to use
1426 plaintext. The second password is ignored */
1428 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) == 0) {
1429 if (!lp_client_plaintext_auth() && (*pass
)) {
1430 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
1431 " or 'client ntlmv2 auth = yes'\n"));
1432 return NT_STATUS_ACCESS_DENIED
;
1434 return cli_session_setup_plaintext(cli
, user
, pass
, workgroup
);
1437 /* if the server supports extended security then use SPNEGO */
1439 if (cli
->capabilities
& CAP_EXTENDED_SECURITY
) {
1440 ADS_STATUS status
= cli_session_setup_spnego(cli
, user
, pass
,
1442 if (!ADS_ERR_OK(status
)) {
1443 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status
)));
1444 return ads_ntstatus(status
);
1449 /* otherwise do a NT1 style session setup */
1450 status
= cli_session_setup_nt1(cli
, user
, pass
, passlen
,
1451 ntpass
, ntpasslen
, workgroup
);
1452 if (!NT_STATUS_IS_OK(status
)) {
1453 DEBUG(3,("cli_session_setup: NT1 session setup "
1454 "failed: %s\n", nt_errstr(status
)));
1459 if (strstr(cli
->server_type
, "Samba")) {
1460 cli
->is_samba
= True
;
1463 return NT_STATUS_OK
;
1466 /****************************************************************************
1468 *****************************************************************************/
1470 struct cli_ulogoff_state
{
1471 struct cli_state
*cli
;
1475 static void cli_ulogoff_done(struct tevent_req
*subreq
);
1477 struct tevent_req
*cli_ulogoff_send(TALLOC_CTX
*mem_ctx
,
1478 struct tevent_context
*ev
,
1479 struct cli_state
*cli
)
1481 struct tevent_req
*req
, *subreq
;
1482 struct cli_ulogoff_state
*state
;
1484 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ulogoff_state
);
1490 SCVAL(state
->vwv
+0, 0, 0xFF);
1491 SCVAL(state
->vwv
+1, 0, 0);
1492 SSVAL(state
->vwv
+2, 0, 0);
1494 subreq
= cli_smb_send(state
, ev
, cli
, SMBulogoffX
, 0, 2, state
->vwv
,
1496 if (tevent_req_nomem(subreq
, req
)) {
1497 return tevent_req_post(req
, ev
);
1499 tevent_req_set_callback(subreq
, cli_ulogoff_done
, req
);
1503 static void cli_ulogoff_done(struct tevent_req
*subreq
)
1505 struct tevent_req
*req
= tevent_req_callback_data(
1506 subreq
, struct tevent_req
);
1507 struct cli_ulogoff_state
*state
= tevent_req_data(
1508 req
, struct cli_ulogoff_state
);
1511 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1512 if (!NT_STATUS_IS_OK(status
)) {
1513 tevent_req_nterror(req
, status
);
1516 state
->cli
->vuid
= -1;
1517 tevent_req_done(req
);
1520 NTSTATUS
cli_ulogoff_recv(struct tevent_req
*req
)
1522 return tevent_req_simple_recv_ntstatus(req
);
1525 NTSTATUS
cli_ulogoff(struct cli_state
*cli
)
1527 struct tevent_context
*ev
;
1528 struct tevent_req
*req
;
1529 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1531 if (cli_has_async_calls(cli
)) {
1532 return NT_STATUS_INVALID_PARAMETER
;
1534 ev
= tevent_context_init(talloc_tos());
1538 req
= cli_ulogoff_send(ev
, ev
, cli
);
1542 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1545 status
= cli_ulogoff_recv(req
);
1548 if (!NT_STATUS_IS_OK(status
)) {
1549 cli_set_error(cli
, status
);
1554 /****************************************************************************
1556 ****************************************************************************/
1558 struct cli_tcon_andx_state
{
1559 struct cli_state
*cli
;
1564 static void cli_tcon_andx_done(struct tevent_req
*subreq
);
1566 struct tevent_req
*cli_tcon_andx_create(TALLOC_CTX
*mem_ctx
,
1567 struct event_context
*ev
,
1568 struct cli_state
*cli
,
1569 const char *share
, const char *dev
,
1570 const char *pass
, int passlen
,
1571 struct tevent_req
**psmbreq
)
1573 struct tevent_req
*req
, *subreq
;
1574 struct cli_tcon_andx_state
*state
;
1582 req
= tevent_req_create(mem_ctx
, &state
, struct cli_tcon_andx_state
);
1589 fstrcpy(cli
->share
, share
);
1591 /* in user level security don't send a password now */
1592 if (cli
->sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
) {
1595 } else if (pass
== NULL
) {
1596 DEBUG(1, ("Server not using user level security and no "
1597 "password supplied.\n"));
1601 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) &&
1602 *pass
&& passlen
!= 24) {
1603 if (!lp_client_lanman_auth()) {
1604 DEBUG(1, ("Server requested LANMAN password "
1605 "(share-level security) but "
1606 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
1611 * Non-encrypted passwords - convert to DOS codepage before
1615 SMBencrypt(pass
, cli
->secblob
.data
, (uchar
*)pword
);
1617 if((cli
->sec_mode
& (NEGOTIATE_SECURITY_USER_LEVEL
1618 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
))
1620 if (!lp_client_plaintext_auth() && (*pass
)) {
1621 DEBUG(1, ("Server requested plaintext "
1623 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
1628 * Non-encrypted passwords - convert to DOS codepage
1631 passlen
= clistr_push(cli
, pword
, pass
, sizeof(pword
),
1633 if (passlen
== -1) {
1634 DEBUG(1, ("clistr_push(pword) failed\n"));
1639 memcpy(pword
, pass
, passlen
);
1644 SCVAL(vwv
+0, 0, 0xFF);
1647 SSVAL(vwv
+2, 0, TCONX_FLAG_EXTENDED_RESPONSE
);
1648 SSVAL(vwv
+3, 0, passlen
);
1651 bytes
= (uint8_t *)talloc_memdup(state
, pword
, passlen
);
1653 bytes
= talloc_array(state
, uint8_t, 0);
1659 tmp
= talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1660 cli
->desthost
, share
);
1665 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), tmp
, strlen(tmp
)+1,
1670 * Add the devicetype
1672 tmp
= talloc_strdup_upper(talloc_tos(), dev
);
1677 bytes
= smb_bytes_push_str(bytes
, false, tmp
, strlen(tmp
)+1, NULL
);
1680 if (bytes
== NULL
) {
1685 state
->bytes
.iov_base
= (void *)bytes
;
1686 state
->bytes
.iov_len
= talloc_get_size(bytes
);
1688 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBtconX
, 0, 4, vwv
,
1690 if (subreq
== NULL
) {
1694 tevent_req_set_callback(subreq
, cli_tcon_andx_done
, req
);
1699 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1700 return tevent_req_post(req
, ev
);
1703 struct tevent_req
*cli_tcon_andx_send(TALLOC_CTX
*mem_ctx
,
1704 struct event_context
*ev
,
1705 struct cli_state
*cli
,
1706 const char *share
, const char *dev
,
1707 const char *pass
, int passlen
)
1709 struct tevent_req
*req
, *subreq
;
1712 req
= cli_tcon_andx_create(mem_ctx
, ev
, cli
, share
, dev
, pass
, passlen
,
1717 if (subreq
== NULL
) {
1720 status
= cli_smb_req_send(subreq
);
1721 if (!NT_STATUS_IS_OK(status
)) {
1722 tevent_req_nterror(req
, status
);
1723 return tevent_req_post(req
, ev
);
1728 static void cli_tcon_andx_done(struct tevent_req
*subreq
)
1730 struct tevent_req
*req
= tevent_req_callback_data(
1731 subreq
, struct tevent_req
);
1732 struct cli_tcon_andx_state
*state
= tevent_req_data(
1733 req
, struct cli_tcon_andx_state
);
1734 struct cli_state
*cli
= state
->cli
;
1743 status
= cli_smb_recv(subreq
, state
, &in
, 0, &wct
, &vwv
,
1744 &num_bytes
, &bytes
);
1745 TALLOC_FREE(subreq
);
1746 if (!NT_STATUS_IS_OK(status
)) {
1747 tevent_req_nterror(req
, status
);
1753 clistr_pull(inbuf
, cli
->dev
, bytes
, sizeof(fstring
), num_bytes
,
1754 STR_TERMINATE
|STR_ASCII
);
1756 if ((cli
->protocol
>= PROTOCOL_NT1
) && (num_bytes
== 3)) {
1757 /* almost certainly win95 - enable bug fixes */
1762 * Make sure that we have the optional support 16-bit field. WCT > 2.
1763 * Avoids issues when connecting to Win9x boxes sharing files
1766 cli
->dfsroot
= false;
1768 if ((wct
> 2) && (cli
->protocol
>= PROTOCOL_LANMAN2
)) {
1769 cli
->dfsroot
= ((SVAL(vwv
+2, 0) & SMB_SHARE_IN_DFS
) != 0);
1772 cli
->cnum
= SVAL(inbuf
,smb_tid
);
1773 tevent_req_done(req
);
1776 NTSTATUS
cli_tcon_andx_recv(struct tevent_req
*req
)
1778 return tevent_req_simple_recv_ntstatus(req
);
1781 NTSTATUS
cli_tcon_andx(struct cli_state
*cli
, const char *share
,
1782 const char *dev
, const char *pass
, int passlen
)
1784 TALLOC_CTX
*frame
= talloc_stackframe();
1785 struct event_context
*ev
;
1786 struct tevent_req
*req
;
1787 NTSTATUS status
= NT_STATUS_OK
;
1789 if (cli_has_async_calls(cli
)) {
1791 * Can't use sync call while an async call is in flight
1793 status
= NT_STATUS_INVALID_PARAMETER
;
1797 ev
= event_context_init(frame
);
1799 status
= NT_STATUS_NO_MEMORY
;
1803 req
= cli_tcon_andx_send(frame
, ev
, cli
, share
, dev
, pass
, passlen
);
1805 status
= NT_STATUS_NO_MEMORY
;
1809 if (!tevent_req_poll(req
, ev
)) {
1810 status
= map_nt_error_from_unix(errno
);
1814 status
= cli_tcon_andx_recv(req
);
1817 if (!NT_STATUS_IS_OK(status
)) {
1818 cli_set_error(cli
, status
);
1823 /****************************************************************************
1824 Send a tree disconnect.
1825 ****************************************************************************/
1827 struct cli_tdis_state
{
1828 struct cli_state
*cli
;
1831 static void cli_tdis_done(struct tevent_req
*subreq
);
1833 struct tevent_req
*cli_tdis_send(TALLOC_CTX
*mem_ctx
,
1834 struct tevent_context
*ev
,
1835 struct cli_state
*cli
)
1837 struct tevent_req
*req
, *subreq
;
1838 struct cli_tdis_state
*state
;
1840 req
= tevent_req_create(mem_ctx
, &state
, struct cli_tdis_state
);
1846 subreq
= cli_smb_send(state
, ev
, cli
, SMBtdis
, 0, 0, NULL
, 0, NULL
);
1847 if (tevent_req_nomem(subreq
, req
)) {
1848 return tevent_req_post(req
, ev
);
1850 tevent_req_set_callback(subreq
, cli_tdis_done
, req
);
1854 static void cli_tdis_done(struct tevent_req
*subreq
)
1856 struct tevent_req
*req
= tevent_req_callback_data(
1857 subreq
, struct tevent_req
);
1858 struct cli_tdis_state
*state
= tevent_req_data(
1859 req
, struct cli_tdis_state
);
1862 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1863 TALLOC_FREE(subreq
);
1864 if (!NT_STATUS_IS_OK(status
)) {
1865 tevent_req_nterror(req
, status
);
1868 state
->cli
->cnum
= -1;
1869 tevent_req_done(req
);
1872 NTSTATUS
cli_tdis_recv(struct tevent_req
*req
)
1874 return tevent_req_simple_recv_ntstatus(req
);
1877 NTSTATUS
cli_tdis(struct cli_state
*cli
)
1879 struct tevent_context
*ev
;
1880 struct tevent_req
*req
;
1881 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1883 if (cli_has_async_calls(cli
)) {
1884 return NT_STATUS_INVALID_PARAMETER
;
1886 ev
= tevent_context_init(talloc_tos());
1890 req
= cli_tdis_send(ev
, ev
, cli
);
1894 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1897 status
= cli_tdis_recv(req
);
1900 if (!NT_STATUS_IS_OK(status
)) {
1901 cli_set_error(cli
, status
);
1906 /****************************************************************************
1907 Send a negprot command.
1908 ****************************************************************************/
1910 struct cli_negprot_state
{
1911 struct cli_state
*cli
;
1914 static void cli_negprot_done(struct tevent_req
*subreq
);
1916 struct tevent_req
*cli_negprot_send(TALLOC_CTX
*mem_ctx
,
1917 struct event_context
*ev
,
1918 struct cli_state
*cli
)
1920 struct tevent_req
*req
, *subreq
;
1921 struct cli_negprot_state
*state
;
1922 uint8_t *bytes
= NULL
;
1926 req
= tevent_req_create(mem_ctx
, &state
, struct cli_negprot_state
);
1932 if (cli
->protocol
< PROTOCOL_NT1
)
1933 cli
->use_spnego
= False
;
1935 /* setup the protocol strings */
1936 for (numprots
=0; numprots
< ARRAY_SIZE(prots
); numprots
++) {
1938 if (prots
[numprots
].prot
> cli
->protocol
) {
1941 bytes
= (uint8_t *)talloc_append_blob(
1942 state
, bytes
, data_blob_const(&c
, sizeof(c
)));
1943 if (tevent_req_nomem(bytes
, req
)) {
1944 return tevent_req_post(req
, ev
);
1946 bytes
= smb_bytes_push_str(bytes
, false,
1947 prots
[numprots
].name
,
1948 strlen(prots
[numprots
].name
)+1,
1950 if (tevent_req_nomem(bytes
, req
)) {
1951 return tevent_req_post(req
, ev
);
1958 subreq
= cli_smb_send(state
, ev
, cli
, SMBnegprot
, 0, 0, NULL
,
1959 talloc_get_size(bytes
), bytes
);
1962 if (tevent_req_nomem(subreq
, req
)) {
1963 return tevent_req_post(req
, ev
);
1965 tevent_req_set_callback(subreq
, cli_negprot_done
, req
);
1969 static void cli_negprot_done(struct tevent_req
*subreq
)
1971 struct tevent_req
*req
= tevent_req_callback_data(
1972 subreq
, struct tevent_req
);
1973 struct cli_negprot_state
*state
= tevent_req_data(
1974 req
, struct cli_negprot_state
);
1975 struct cli_state
*cli
= state
->cli
;
1984 status
= cli_smb_recv(subreq
, state
, &inbuf
, 1, &wct
, &vwv
,
1985 &num_bytes
, &bytes
);
1986 TALLOC_FREE(subreq
);
1987 if (!NT_STATUS_IS_OK(status
)) {
1988 tevent_req_nterror(req
, status
);
1992 protnum
= SVAL(vwv
, 0);
1994 if ((protnum
>= ARRAY_SIZE(prots
))
1995 || (prots
[protnum
].prot
> cli
->protocol
)) {
1996 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
2000 cli
->protocol
= prots
[protnum
].prot
;
2002 if ((cli
->protocol
< PROTOCOL_NT1
) &&
2003 client_is_signing_mandatory(cli
)) {
2004 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2005 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2009 if (cli
->protocol
>= PROTOCOL_NT1
) {
2011 bool negotiated_smb_signing
= false;
2014 cli
->sec_mode
= CVAL(vwv
+ 1, 0);
2015 cli
->max_mux
= SVAL(vwv
+ 1, 1);
2016 cli
->max_xmit
= IVAL(vwv
+ 3, 1);
2017 cli
->sesskey
= IVAL(vwv
+ 7, 1);
2018 cli
->serverzone
= SVALS(vwv
+ 15, 1);
2019 cli
->serverzone
*= 60;
2020 /* this time arrives in real GMT */
2021 ts
= interpret_long_date(((char *)(vwv
+11))+1);
2022 cli
->servertime
= ts
.tv_sec
;
2023 cli
->secblob
= data_blob(bytes
, num_bytes
);
2024 cli
->capabilities
= IVAL(vwv
+ 9, 1);
2025 if (cli
->capabilities
& CAP_RAW_MODE
) {
2026 cli
->readbraw_supported
= True
;
2027 cli
->writebraw_supported
= True
;
2029 /* work out if they sent us a workgroup */
2030 if (!(cli
->capabilities
& CAP_EXTENDED_SECURITY
) &&
2031 smb_buflen(cli
->inbuf
) > 8) {
2032 clistr_pull(cli
->inbuf
, cli
->server_domain
,
2033 bytes
+8, sizeof(cli
->server_domain
),
2035 STR_UNICODE
|STR_NOALIGN
);
2039 * As signing is slow we only turn it on if either the client or
2040 * the server require it. JRA.
2043 if (cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_REQUIRED
) {
2044 /* Fail if server says signing is mandatory and we don't want to support it. */
2045 if (!client_is_signing_allowed(cli
)) {
2046 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2047 tevent_req_nterror(req
,
2048 NT_STATUS_ACCESS_DENIED
);
2051 negotiated_smb_signing
= true;
2052 } else if (client_is_signing_mandatory(cli
) && client_is_signing_allowed(cli
)) {
2053 /* Fail if client says signing is mandatory and the server doesn't support it. */
2054 if (!(cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_ENABLED
)) {
2055 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2056 tevent_req_nterror(req
,
2057 NT_STATUS_ACCESS_DENIED
);
2060 negotiated_smb_signing
= true;
2061 } else if (cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_ENABLED
) {
2062 negotiated_smb_signing
= true;
2065 if (negotiated_smb_signing
) {
2066 cli_set_signing_negotiated(cli
);
2069 if (cli
->capabilities
& (CAP_LARGE_READX
|CAP_LARGE_WRITEX
)) {
2070 SAFE_FREE(cli
->outbuf
);
2071 SAFE_FREE(cli
->inbuf
);
2072 cli
->outbuf
= (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE
+LARGE_WRITEX_HDR_SIZE
+SAFETY_MARGIN
);
2073 cli
->inbuf
= (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE
+LARGE_WRITEX_HDR_SIZE
+SAFETY_MARGIN
);
2074 if (!cli
->outbuf
|| !cli
->inbuf
) {
2075 tevent_req_nterror(req
,
2076 NT_STATUS_NO_MEMORY
);
2079 cli
->bufsize
= CLI_SAMBA_MAX_LARGE_READX_SIZE
+ LARGE_WRITEX_HDR_SIZE
;
2082 } else if (cli
->protocol
>= PROTOCOL_LANMAN1
) {
2083 cli
->use_spnego
= False
;
2084 cli
->sec_mode
= SVAL(vwv
+ 1, 0);
2085 cli
->max_xmit
= SVAL(vwv
+ 2, 0);
2086 cli
->max_mux
= SVAL(vwv
+ 3, 0);
2087 cli
->sesskey
= IVAL(vwv
+ 6, 0);
2088 cli
->serverzone
= SVALS(vwv
+ 10, 0);
2089 cli
->serverzone
*= 60;
2090 /* this time is converted to GMT by make_unix_date */
2091 cli
->servertime
= make_unix_date(
2092 (char *)(vwv
+ 8), cli
->serverzone
);
2093 cli
->readbraw_supported
= ((SVAL(vwv
+ 5, 0) & 0x1) != 0);
2094 cli
->writebraw_supported
= ((SVAL(vwv
+ 5, 0) & 0x2) != 0);
2095 cli
->secblob
= data_blob(bytes
, num_bytes
);
2097 /* the old core protocol */
2098 cli
->use_spnego
= False
;
2100 cli
->serverzone
= get_time_zone(time(NULL
));
2103 cli
->max_xmit
= MIN(cli
->max_xmit
, CLI_BUFFER_SIZE
);
2105 /* a way to force ascii SMB */
2106 if (getenv("CLI_FORCE_ASCII"))
2107 cli
->capabilities
&= ~CAP_UNICODE
;
2109 tevent_req_done(req
);
2112 NTSTATUS
cli_negprot_recv(struct tevent_req
*req
)
2114 return tevent_req_simple_recv_ntstatus(req
);
2117 NTSTATUS
cli_negprot(struct cli_state
*cli
)
2119 TALLOC_CTX
*frame
= talloc_stackframe();
2120 struct event_context
*ev
;
2121 struct tevent_req
*req
;
2122 NTSTATUS status
= NT_STATUS_OK
;
2124 if (cli_has_async_calls(cli
)) {
2126 * Can't use sync call while an async call is in flight
2128 status
= NT_STATUS_INVALID_PARAMETER
;
2132 ev
= event_context_init(frame
);
2134 status
= NT_STATUS_NO_MEMORY
;
2138 req
= cli_negprot_send(frame
, ev
, cli
);
2140 status
= NT_STATUS_NO_MEMORY
;
2144 if (!tevent_req_poll(req
, ev
)) {
2145 status
= map_nt_error_from_unix(errno
);
2149 status
= cli_negprot_recv(req
);
2152 if (!NT_STATUS_IS_OK(status
)) {
2153 cli_set_error(cli
, status
);
2158 /****************************************************************************
2159 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
2160 ****************************************************************************/
2162 bool cli_session_request(struct cli_state
*cli
,
2163 struct nmb_name
*calling
, struct nmb_name
*called
)
2170 /* 445 doesn't have session request */
2171 if (cli
->port
== 445)
2174 memcpy(&(cli
->calling
), calling
, sizeof(*calling
));
2175 memcpy(&(cli
->called
), called
, sizeof(*called
));
2177 /* put in the destination name */
2179 tmp
= name_mangle(talloc_tos(), cli
->called
.name
,
2180 cli
->called
.name_type
);
2185 p
= cli
->outbuf
+len
;
2186 namelen
= name_len((unsigned char *)tmp
, talloc_get_size(tmp
));
2188 memcpy(p
, tmp
, namelen
);
2195 tmp
= name_mangle(talloc_tos(), cli
->calling
.name
,
2196 cli
->calling
.name_type
);
2201 p
= cli
->outbuf
+len
;
2202 namelen
= name_len((unsigned char *)tmp
, talloc_get_size(tmp
));
2204 memcpy(p
, tmp
, namelen
);
2209 /* send a session request (RFC 1002) */
2210 /* setup the packet length
2211 * Remove four bytes from the length count, since the length
2212 * field in the NBT Session Service header counts the number
2213 * of bytes which follow. The cli_send_smb() function knows
2214 * about this and accounts for those four bytes.
2218 _smb_setlen(cli
->outbuf
,len
);
2219 SCVAL(cli
->outbuf
,0,0x81);
2222 DEBUG(5,("Sent session request\n"));
2224 if (!cli_receive_smb(cli
))
2227 if (CVAL(cli
->inbuf
,0) == 0x84) {
2228 /* C. Hoch 9/14/95 Start */
2229 /* For information, here is the response structure.
2230 * We do the byte-twiddling to for portability.
2231 struct RetargetResponse{
2233 unsigned char flags;
2239 uint16_t port
= (CVAL(cli
->inbuf
,8)<<8)+CVAL(cli
->inbuf
,9);
2240 struct in_addr dest_ip
;
2243 /* SESSION RETARGET */
2244 putip((char *)&dest_ip
,cli
->inbuf
+4);
2245 in_addr_to_sockaddr_storage(&cli
->dest_ss
, dest_ip
);
2247 status
= open_socket_out(&cli
->dest_ss
, port
,
2248 LONG_CONNECT_TIMEOUT
, &cli
->fd
);
2249 if (!NT_STATUS_IS_OK(status
)) {
2253 DEBUG(3,("Retargeted\n"));
2255 set_socket_options(cli
->fd
, lp_socket_options());
2262 DEBUG(0,("Retarget recursion - failing\n"));
2266 ret
= cli_session_request(cli
, calling
, called
);
2270 } /* C. Hoch 9/14/95 End */
2272 if (CVAL(cli
->inbuf
,0) != 0x82) {
2273 /* This is the wrong place to put the error... JRA. */
2274 cli
->rap_error
= CVAL(cli
->inbuf
,4);
2284 static void smb_sock_connected(struct tevent_req
*req
)
2286 struct fd_struct
*pfd
= tevent_req_callback_data(
2287 req
, struct fd_struct
);
2291 status
= open_socket_out_defer_recv(req
, &fd
);
2292 if (NT_STATUS_IS_OK(status
)) {
2297 static NTSTATUS
open_smb_socket(const struct sockaddr_storage
*pss
,
2298 uint16_t *port
, int timeout
, int *pfd
)
2300 struct event_context
*ev
;
2301 struct tevent_req
*r139
, *r445
;
2302 struct fd_struct
*fd139
, *fd445
;
2303 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2306 return open_socket_out(pss
, *port
, timeout
, pfd
);
2309 ev
= event_context_init(talloc_tos());
2311 return NT_STATUS_NO_MEMORY
;
2314 fd139
= talloc(ev
, struct fd_struct
);
2315 if (fd139
== NULL
) {
2320 fd445
= talloc(ev
, struct fd_struct
);
2321 if (fd445
== NULL
) {
2326 r445
= open_socket_out_defer_send(ev
, ev
, timeval_set(0, 0),
2328 r139
= open_socket_out_defer_send(ev
, ev
, timeval_set(0, 3000),
2330 if ((r445
== NULL
) || (r139
== NULL
)) {
2333 tevent_req_set_callback(r445
, smb_sock_connected
, fd445
);
2334 tevent_req_set_callback(r139
, smb_sock_connected
, fd139
);
2336 while ((fd445
->fd
== -1) && (fd139
->fd
== -1)
2337 && (tevent_req_is_in_progress(r139
)
2338 || tevent_req_is_in_progress(r445
))) {
2339 event_loop_once(ev
);
2342 if ((fd139
->fd
!= -1) && (fd445
->fd
!= -1)) {
2347 if (fd445
->fd
!= -1) {
2350 status
= NT_STATUS_OK
;
2353 if (fd139
->fd
!= -1) {
2356 status
= NT_STATUS_OK
;
2360 status
= open_socket_out_defer_recv(r445
, &fd445
->fd
);
2366 /****************************************************************************
2367 Open the client sockets.
2368 ****************************************************************************/
2370 NTSTATUS
cli_connect(struct cli_state
*cli
,
2372 struct sockaddr_storage
*dest_ss
)
2375 int name_type
= 0x20;
2376 TALLOC_CTX
*frame
= talloc_stackframe();
2377 unsigned int num_addrs
= 0;
2379 struct sockaddr_storage
*ss_arr
= NULL
;
2382 /* reasonable default hostname */
2384 host
= STAR_SMBSERVER
;
2387 fstrcpy(cli
->desthost
, host
);
2389 /* allow hostnames of the form NAME#xx and do a netbios lookup */
2390 if ((p
= strchr(cli
->desthost
, '#'))) {
2391 name_type
= strtol(p
+1, NULL
, 16);
2395 if (!dest_ss
|| is_zero_addr(dest_ss
)) {
2396 NTSTATUS status
=resolve_name_list(frame
,
2401 if (!NT_STATUS_IS_OK(status
)) {
2403 return NT_STATUS_BAD_NETWORK_NAME
;
2407 ss_arr
= TALLOC_P(frame
, struct sockaddr_storage
);
2410 return NT_STATUS_NO_MEMORY
;
2415 for (i
= 0; i
< num_addrs
; i
++) {
2416 cli
->dest_ss
= ss_arr
[i
];
2417 if (getenv("LIBSMB_PROG")) {
2418 cli
->fd
= sock_exec(getenv("LIBSMB_PROG"));
2420 uint16_t port
= cli
->port
;
2422 status
= open_smb_socket(&cli
->dest_ss
, &port
,
2423 cli
->timeout
, &cli
->fd
);
2424 if (NT_STATUS_IS_OK(status
)) {
2428 if (cli
->fd
== -1) {
2429 char addr
[INET6_ADDRSTRLEN
];
2430 print_sockaddr(addr
, sizeof(addr
), &ss_arr
[i
]);
2431 DEBUG(2,("Error connecting to %s (%s)\n",
2432 dest_ss
?addr
:host
,strerror(errno
)));
2434 /* Exit from loop on first connection. */
2439 if (cli
->fd
== -1) {
2441 return map_nt_error_from_unix(errno
);
2445 *dest_ss
= cli
->dest_ss
;
2448 set_socket_options(cli
->fd
, lp_socket_options());
2451 return NT_STATUS_OK
;
2455 establishes a connection to after the negprot.
2456 @param output_cli A fully initialised cli structure, non-null only on success
2457 @param dest_host The netbios name of the remote host
2458 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2459 @param port (optional) The destination port (0 for default)
2461 NTSTATUS
cli_start_connection(struct cli_state
**output_cli
,
2462 const char *my_name
,
2463 const char *dest_host
,
2464 struct sockaddr_storage
*dest_ss
, int port
,
2465 int signing_state
, int flags
)
2468 struct nmb_name calling
;
2469 struct nmb_name called
;
2470 struct cli_state
*cli
;
2471 struct sockaddr_storage ss
;
2474 my_name
= global_myname();
2476 if (!(cli
= cli_initialise_ex(signing_state
))) {
2477 return NT_STATUS_NO_MEMORY
;
2480 make_nmb_name(&calling
, my_name
, 0x0);
2481 make_nmb_name(&called
, dest_host
, 0x20);
2483 cli_set_port(cli
, port
);
2484 cli_set_timeout(cli
, 10000); /* 10 seconds. */
2494 DEBUG(3,("Connecting to host=%s\n", dest_host
));
2496 nt_status
= cli_connect(cli
, dest_host
, &ss
);
2497 if (!NT_STATUS_IS_OK(nt_status
)) {
2498 char addr
[INET6_ADDRSTRLEN
];
2499 print_sockaddr(addr
, sizeof(addr
), &ss
);
2500 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
2501 nmb_namestr(&called
), addr
, nt_errstr(nt_status
) ));
2506 if (!cli_session_request(cli
, &calling
, &called
)) {
2508 DEBUG(1,("session request to %s failed (%s)\n",
2509 called
.name
, cli_errstr(cli
)));
2510 if ((p
=strchr(called
.name
, '.')) && !is_ipaddress(called
.name
)) {
2514 if (strcmp(called
.name
, STAR_SMBSERVER
)) {
2515 make_nmb_name(&called
, STAR_SMBSERVER
, 0x20);
2518 return NT_STATUS_BAD_NETWORK_NAME
;
2521 if (flags
& CLI_FULL_CONNECTION_DONT_SPNEGO
)
2522 cli
->use_spnego
= False
;
2523 else if (flags
& CLI_FULL_CONNECTION_USE_KERBEROS
)
2524 cli
->use_kerberos
= True
;
2526 if ((flags
& CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS
) &&
2527 cli
->use_kerberos
) {
2528 cli
->fallback_after_kerberos
= true;
2530 if (flags
& CLI_FULL_CONNECTION_USE_CCACHE
) {
2531 cli
->use_ccache
= true;
2534 nt_status
= cli_negprot(cli
);
2535 if (!NT_STATUS_IS_OK(nt_status
)) {
2536 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status
)));
2542 return NT_STATUS_OK
;
2547 establishes a connection right up to doing tconX, password specified.
2548 @param output_cli A fully initialised cli structure, non-null only on success
2549 @param dest_host The netbios name of the remote host
2550 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2551 @param port (optional) The destination port (0 for default)
2552 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2553 @param service_type The 'type' of serivice.
2554 @param user Username, unix string
2555 @param domain User's domain
2556 @param password User's password, unencrypted unix string.
2559 NTSTATUS
cli_full_connection(struct cli_state
**output_cli
,
2560 const char *my_name
,
2561 const char *dest_host
,
2562 struct sockaddr_storage
*dest_ss
, int port
,
2563 const char *service
, const char *service_type
,
2564 const char *user
, const char *domain
,
2565 const char *password
, int flags
,
2569 struct cli_state
*cli
= NULL
;
2570 int pw_len
= password
? strlen(password
)+1 : 0;
2574 if (password
== NULL
) {
2578 nt_status
= cli_start_connection(&cli
, my_name
, dest_host
,
2579 dest_ss
, port
, signing_state
,
2582 if (!NT_STATUS_IS_OK(nt_status
)) {
2586 cli
->use_oplocks
= ((flags
& CLI_FULL_CONNECTION_OPLOCKS
) != 0);
2587 cli
->use_level_II_oplocks
=
2588 ((flags
& CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS
) != 0);
2590 nt_status
= cli_session_setup(cli
, user
, password
, pw_len
, password
,
2592 if (!NT_STATUS_IS_OK(nt_status
)) {
2594 if (!(flags
& CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK
)) {
2595 DEBUG(1,("failed session setup with %s\n",
2596 nt_errstr(nt_status
)));
2601 nt_status
= cli_session_setup(cli
, "", "", 0, "", 0, domain
);
2602 if (!NT_STATUS_IS_OK(nt_status
)) {
2603 DEBUG(1,("anonymous failed session setup with %s\n",
2604 nt_errstr(nt_status
)));
2611 nt_status
= cli_tcon_andx(cli
, service
, service_type
, password
,
2613 if (!NT_STATUS_IS_OK(nt_status
)) {
2614 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status
)));
2616 if (NT_STATUS_IS_OK(nt_status
)) {
2617 nt_status
= NT_STATUS_UNSUCCESSFUL
;
2623 nt_status
= cli_init_creds(cli
, user
, domain
, password
);
2624 if (!NT_STATUS_IS_OK(nt_status
)) {
2630 return NT_STATUS_OK
;
2633 /****************************************************************************
2634 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2635 ****************************************************************************/
2637 bool attempt_netbios_session_request(struct cli_state
**ppcli
, const char *srchost
, const char *desthost
,
2638 struct sockaddr_storage
*pdest_ss
)
2640 struct nmb_name calling
, called
;
2642 make_nmb_name(&calling
, srchost
, 0x0);
2645 * If the called name is an IP address
2646 * then use *SMBSERVER immediately.
2649 if(is_ipaddress(desthost
)) {
2650 make_nmb_name(&called
, STAR_SMBSERVER
, 0x20);
2652 make_nmb_name(&called
, desthost
, 0x20);
2655 if (!cli_session_request(*ppcli
, &calling
, &called
)) {
2657 struct nmb_name smbservername
;
2659 make_nmb_name(&smbservername
, STAR_SMBSERVER
, 0x20);
2662 * If the name wasn't *SMBSERVER then
2663 * try with *SMBSERVER if the first name fails.
2666 if (nmb_name_equal(&called
, &smbservername
)) {
2669 * The name used was *SMBSERVER, don't bother with another name.
2672 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2673 with error %s.\n", desthost
, cli_errstr(*ppcli
) ));
2678 cli_shutdown(*ppcli
);
2680 *ppcli
= cli_initialise();
2682 /* Out of memory... */
2686 status
= cli_connect(*ppcli
, desthost
, pdest_ss
);
2687 if (!NT_STATUS_IS_OK(status
) ||
2688 !cli_session_request(*ppcli
, &calling
, &smbservername
)) {
2689 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2690 name *SMBSERVER with error %s\n", desthost
, cli_errstr(*ppcli
) ));
2698 /****************************************************************************
2699 Send an old style tcon.
2700 ****************************************************************************/
2701 NTSTATUS
cli_raw_tcon(struct cli_state
*cli
,
2702 const char *service
, const char *pass
, const char *dev
,
2703 uint16
*max_xmit
, uint16
*tid
)
2705 struct tevent_req
*req
;
2710 if (!lp_client_plaintext_auth() && (*pass
)) {
2711 DEBUG(1, ("Server requested plaintext password but 'client "
2712 "plaintext auth' is disabled\n"));
2713 return NT_STATUS_ACCESS_DENIED
;
2716 bytes
= talloc_array(talloc_tos(), uint8_t, 0);
2717 bytes
= smb_bytes_push_bytes(bytes
, 4, NULL
, 0);
2718 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
2719 service
, strlen(service
)+1, NULL
);
2720 bytes
= smb_bytes_push_bytes(bytes
, 4, NULL
, 0);
2721 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
2722 pass
, strlen(pass
)+1, NULL
);
2723 bytes
= smb_bytes_push_bytes(bytes
, 4, NULL
, 0);
2724 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
2725 dev
, strlen(dev
)+1, NULL
);
2727 status
= cli_smb(talloc_tos(), cli
, SMBtcon
, 0, 0, NULL
,
2728 talloc_get_size(bytes
), bytes
, &req
,
2729 2, NULL
, &ret_vwv
, NULL
, NULL
);
2730 if (!NT_STATUS_IS_OK(status
)) {
2734 *max_xmit
= SVAL(ret_vwv
+ 0, 0);
2735 *tid
= SVAL(ret_vwv
+ 1, 0);
2737 return NT_STATUS_OK
;
2740 /* Return a cli_state pointing at the IPC$ share for the given server */
2742 struct cli_state
*get_ipc_connect(char *server
,
2743 struct sockaddr_storage
*server_ss
,
2744 const struct user_auth_info
*user_info
)
2746 struct cli_state
*cli
;
2748 uint32_t flags
= CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK
;
2750 if (user_info
->use_kerberos
) {
2751 flags
|= CLI_FULL_CONNECTION_USE_KERBEROS
;
2754 nt_status
= cli_full_connection(&cli
, NULL
, server
, server_ss
, 0, "IPC$", "IPC",
2755 user_info
->username
? user_info
->username
: "",
2757 user_info
->password
? user_info
->password
: "",
2761 if (NT_STATUS_IS_OK(nt_status
)) {
2763 } else if (is_ipaddress(server
)) {
2764 /* windows 9* needs a correct NMB name for connections */
2765 fstring remote_name
;
2767 if (name_status_find("*", 0, 0, server_ss
, remote_name
)) {
2768 cli
= get_ipc_connect(remote_name
, server_ss
, user_info
);
2777 * Given the IP address of a master browser on the network, return its
2778 * workgroup and connect to it.
2780 * This function is provided to allow additional processing beyond what
2781 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2782 * browsers and obtain each master browsers' list of domains (in case the
2783 * first master browser is recently on the network and has not yet
2784 * synchronized with other master browsers and therefore does not yet have the
2785 * entire network browse list)
2788 struct cli_state
*get_ipc_connect_master_ip(TALLOC_CTX
*ctx
,
2789 struct ip_service
*mb_ip
,
2790 const struct user_auth_info
*user_info
,
2791 char **pp_workgroup_out
)
2793 char addr
[INET6_ADDRSTRLEN
];
2795 struct cli_state
*cli
;
2796 struct sockaddr_storage server_ss
;
2798 *pp_workgroup_out
= NULL
;
2800 print_sockaddr(addr
, sizeof(addr
), &mb_ip
->ss
);
2801 DEBUG(99, ("Looking up name of master browser %s\n",
2805 * Do a name status query to find out the name of the master browser.
2806 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2807 * master browser will not respond to a wildcard query (or, at least,
2808 * an NT4 server acting as the domain master browser will not).
2810 * We might be able to use ONLY the query on MSBROWSE, but that's not
2811 * yet been tested with all Windows versions, so until it is, leave
2812 * the original wildcard query as the first choice and fall back to
2813 * MSBROWSE if the wildcard query fails.
2815 if (!name_status_find("*", 0, 0x1d, &mb_ip
->ss
, name
) &&
2816 !name_status_find(MSBROWSE
, 1, 0x1d, &mb_ip
->ss
, name
)) {
2818 DEBUG(99, ("Could not retrieve name status for %s\n",
2823 if (!find_master_ip(name
, &server_ss
)) {
2824 DEBUG(99, ("Could not find master ip for %s\n", name
));
2828 *pp_workgroup_out
= talloc_strdup(ctx
, name
);
2830 DEBUG(4, ("found master browser %s, %s\n", name
, addr
));
2832 print_sockaddr(addr
, sizeof(addr
), &server_ss
);
2833 cli
= get_ipc_connect(addr
, &server_ss
, user_info
);
2839 * Return the IP address and workgroup of a master browser on the network, and
2843 struct cli_state
*get_ipc_connect_master_ip_bcast(TALLOC_CTX
*ctx
,
2844 const struct user_auth_info
*user_info
,
2845 char **pp_workgroup_out
)
2847 struct ip_service
*ip_list
;
2848 struct cli_state
*cli
;
2851 *pp_workgroup_out
= NULL
;
2853 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2855 /* Go looking for workgroups by broadcasting on the local network */
2857 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE
, 1, &ip_list
,
2859 DEBUG(99, ("No master browsers responded\n"));
2863 for (i
= 0; i
< count
; i
++) {
2864 char addr
[INET6_ADDRSTRLEN
];
2865 print_sockaddr(addr
, sizeof(addr
), &ip_list
[i
].ss
);
2866 DEBUG(99, ("Found master browser %s\n", addr
));
2868 cli
= get_ipc_connect_master_ip(ctx
, &ip_list
[i
],
2869 user_info
, pp_workgroup_out
);