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/>.
27 {PROTOCOL_CORE
, "PC NETWORK PROGRAM 1.0"},
28 {PROTOCOL_COREPLUS
, "MICROSOFT NETWORKS 1.03"},
29 {PROTOCOL_LANMAN1
, "MICROSOFT NETWORKS 3.0"},
30 {PROTOCOL_LANMAN1
, "LANMAN1.0"},
31 {PROTOCOL_LANMAN2
, "LM1.2X002"},
32 {PROTOCOL_LANMAN2
, "DOS LANMAN2.1"},
33 {PROTOCOL_LANMAN2
, "LANMAN2.1"},
34 {PROTOCOL_LANMAN2
, "Samba"},
35 {PROTOCOL_NT1
, "NT LANMAN 1.0"},
36 {PROTOCOL_NT1
, "NT LM 0.12"},
39 #define STAR_SMBSERVER "*SMBSERVER"
42 * Set the user session key for a connection
43 * @param cli The cli structure to add it too
44 * @param session_key The session key used. (A copy of this is taken for the cli struct)
48 static void cli_set_session_key (struct cli_state
*cli
, const DATA_BLOB session_key
)
50 cli
->user_session_key
= data_blob(session_key
.data
, session_key
.length
);
53 /****************************************************************************
54 Do an old lanman2 style session setup.
55 ****************************************************************************/
57 static NTSTATUS
cli_session_setup_lanman2(struct cli_state
*cli
,
59 const char *pass
, size_t passlen
,
60 const char *workgroup
)
62 DATA_BLOB session_key
= data_blob_null
;
63 DATA_BLOB lm_response
= data_blob_null
;
67 if (passlen
> sizeof(pword
)-1) {
68 return NT_STATUS_INVALID_PARAMETER
;
71 /* LANMAN servers predate NT status codes and Unicode and ignore those
72 smb flags so we must disable the corresponding default capabilities
73 that would otherwise cause the Unicode and NT Status flags to be
74 set (and even returned by the server) */
76 cli
->capabilities
&= ~(CAP_UNICODE
| CAP_STATUS32
);
78 /* if in share level security then don't send a password now */
79 if (!(cli
->sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
))
82 if (passlen
> 0 && (cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) && passlen
!= 24) {
83 /* Encrypted mode needed, and non encrypted password supplied. */
84 lm_response
= data_blob(NULL
, 24);
85 if (!SMBencrypt(pass
, cli
->secblob
.data
,(uchar
*)lm_response
.data
)) {
86 DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
87 return NT_STATUS_ACCESS_DENIED
;
89 } else if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) && passlen
== 24) {
90 /* Encrypted mode needed, and encrypted password supplied. */
91 lm_response
= data_blob(pass
, passlen
);
92 } else if (passlen
> 0) {
93 /* Plaintext mode needed, assume plaintext supplied. */
94 passlen
= clistr_push(cli
, pword
, pass
, sizeof(pword
), STR_TERMINATE
);
95 lm_response
= data_blob(pass
, passlen
);
98 /* send a session setup command */
99 memset(cli
->outbuf
,'\0',smb_size
);
100 cli_set_message(cli
->outbuf
,10, 0, True
);
101 SCVAL(cli
->outbuf
,smb_com
,SMBsesssetupX
);
102 cli_setup_packet(cli
);
104 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
105 SSVAL(cli
->outbuf
,smb_vwv2
,cli
->max_xmit
);
106 SSVAL(cli
->outbuf
,smb_vwv3
,2);
107 SSVAL(cli
->outbuf
,smb_vwv4
,1);
108 SIVAL(cli
->outbuf
,smb_vwv5
,cli
->sesskey
);
109 SSVAL(cli
->outbuf
,smb_vwv7
,lm_response
.length
);
111 p
= smb_buf(cli
->outbuf
);
112 memcpy(p
,lm_response
.data
,lm_response
.length
);
113 p
+= lm_response
.length
;
114 p
+= clistr_push(cli
, p
, user
, -1, STR_TERMINATE
|STR_UPPER
);
115 p
+= clistr_push(cli
, p
, workgroup
, -1, STR_TERMINATE
|STR_UPPER
);
116 p
+= clistr_push(cli
, p
, "Unix", -1, STR_TERMINATE
);
117 p
+= clistr_push(cli
, p
, "Samba", -1, STR_TERMINATE
);
118 cli_setup_bcc(cli
, p
);
120 if (!cli_send_smb(cli
) || !cli_receive_smb(cli
)) {
121 return cli_nt_error(cli
);
124 show_msg(cli
->inbuf
);
126 if (cli_is_error(cli
)) {
127 return cli_nt_error(cli
);
130 /* use the returned vuid from now on */
131 cli
->vuid
= SVAL(cli
->inbuf
,smb_uid
);
132 fstrcpy(cli
->user_name
, user
);
134 if (session_key
.data
) {
135 /* Have plaintext orginal */
136 cli_set_session_key(cli
, session_key
);
142 /****************************************************************************
143 Work out suitable capabilities to offer the server.
144 ****************************************************************************/
146 static uint32
cli_session_setup_capabilities(struct cli_state
*cli
)
148 uint32 capabilities
= CAP_NT_SMBS
;
150 if (!cli
->force_dos_errors
)
151 capabilities
|= CAP_STATUS32
;
153 if (cli
->use_level_II_oplocks
)
154 capabilities
|= CAP_LEVEL_II_OPLOCKS
;
156 capabilities
|= (cli
->capabilities
& (CAP_UNICODE
|CAP_LARGE_FILES
|CAP_LARGE_READX
|CAP_LARGE_WRITEX
|CAP_DFS
));
160 /****************************************************************************
161 Do a NT1 guest session setup.
162 ****************************************************************************/
164 struct async_req
*cli_session_setup_guest_send(TALLOC_CTX
*mem_ctx
,
165 struct event_context
*ev
,
166 struct cli_state
*cli
)
168 struct async_req
*result
;
172 SCVAL(vwv
+0, 0, 0xFF);
175 SSVAL(vwv
+2, 0, CLI_BUFFER_SIZE
);
177 SSVAL(vwv
+4, 0, cli
->pid
);
178 SIVAL(vwv
+5, 0, cli
->sesskey
);
183 SIVAL(vwv
+11, 0, cli_session_setup_capabilities(cli
));
185 bytes
= talloc_array(talloc_tos(), uint8_t, 0);
187 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "", 1, /* username */
189 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "", 1, /* workgroup */
191 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "Unix",
192 strlen("Unix")+1, NULL
);
193 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "Samba",
194 strlen("Samba")+1, NULL
);
200 result
= cli_request_send(mem_ctx
, ev
, cli
, SMBsesssetupX
, 0,
201 13, vwv
, 0, talloc_get_size(bytes
), bytes
);
206 NTSTATUS
cli_session_setup_guest_recv(struct async_req
*req
)
208 struct cli_request
*cli_req
= talloc_get_type_abort(
209 req
->private_data
, struct cli_request
);
210 struct cli_state
*cli
= cli_req
->cli
;
218 if (async_req_is_nterror(req
, &status
)) {
222 status
= cli_pull_reply(req
, &wct
, &vwv
, &num_bytes
, &bytes
);
223 if (!NT_STATUS_IS_OK(status
)) {
229 cli
->vuid
= SVAL(cli_req
->inbuf
, smb_uid
);
231 p
+= clistr_pull(cli_req
->inbuf
, cli
->server_os
, (char *)p
,
232 sizeof(fstring
), bytes
+num_bytes
-p
, STR_TERMINATE
);
233 p
+= clistr_pull(cli_req
->inbuf
, cli
->server_type
, (char *)p
,
234 sizeof(fstring
), bytes
+num_bytes
-p
, STR_TERMINATE
);
235 p
+= clistr_pull(cli_req
->inbuf
, cli
->server_domain
, (char *)p
,
236 sizeof(fstring
), bytes
+num_bytes
-p
, STR_TERMINATE
);
238 if (strstr(cli
->server_type
, "Samba")) {
239 cli
->is_samba
= True
;
242 fstrcpy(cli
->user_name
, "");
247 static NTSTATUS
cli_session_setup_guest(struct cli_state
*cli
)
249 TALLOC_CTX
*frame
= talloc_stackframe();
250 struct event_context
*ev
;
251 struct async_req
*req
;
254 if (cli
->fd_event
!= NULL
) {
256 * Can't use sync call while an async call is in flight
258 status
= NT_STATUS_INVALID_PARAMETER
;
262 ev
= event_context_init(frame
);
264 status
= NT_STATUS_NO_MEMORY
;
268 req
= cli_session_setup_guest_send(frame
, ev
, cli
);
270 status
= NT_STATUS_NO_MEMORY
;
274 while (req
->state
< ASYNC_REQ_DONE
) {
278 status
= cli_session_setup_guest_recv(req
);
284 /****************************************************************************
285 Do a NT1 plaintext session setup.
286 ****************************************************************************/
288 static NTSTATUS
cli_session_setup_plaintext(struct cli_state
*cli
,
289 const char *user
, const char *pass
,
290 const char *workgroup
)
292 uint32 capabilities
= cli_session_setup_capabilities(cli
);
296 fstr_sprintf( lanman
, "Samba %s", samba_version_string());
298 memset(cli
->outbuf
, '\0', smb_size
);
299 cli_set_message(cli
->outbuf
,13,0,True
);
300 SCVAL(cli
->outbuf
,smb_com
,SMBsesssetupX
);
301 cli_setup_packet(cli
);
303 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
304 SSVAL(cli
->outbuf
,smb_vwv2
,CLI_BUFFER_SIZE
);
305 SSVAL(cli
->outbuf
,smb_vwv3
,2);
306 SSVAL(cli
->outbuf
,smb_vwv4
,cli
->pid
);
307 SIVAL(cli
->outbuf
,smb_vwv5
,cli
->sesskey
);
308 SSVAL(cli
->outbuf
,smb_vwv8
,0);
309 SIVAL(cli
->outbuf
,smb_vwv11
,capabilities
);
310 p
= smb_buf(cli
->outbuf
);
312 /* check wether to send the ASCII or UNICODE version of the password */
314 if ( (capabilities
& CAP_UNICODE
) == 0 ) {
315 p
+= clistr_push(cli
, p
, pass
, -1, STR_TERMINATE
); /* password */
316 SSVAL(cli
->outbuf
,smb_vwv7
,PTR_DIFF(p
, smb_buf(cli
->outbuf
)));
319 /* For ucs2 passwords clistr_push calls ucs2_align, which causes
320 * the space taken by the unicode password to be one byte too
321 * long (as we're on an odd byte boundary here). Reduce the
322 * count by 1 to cope with this. Fixes smbclient against NetApp
323 * servers which can't cope. Fix from
324 * bryan.kolodziej@allenlund.com in bug #3840.
326 p
+= clistr_push(cli
, p
, pass
, -1, STR_UNICODE
|STR_TERMINATE
); /* unicode password */
327 SSVAL(cli
->outbuf
,smb_vwv8
,PTR_DIFF(p
, smb_buf(cli
->outbuf
))-1);
330 p
+= clistr_push(cli
, p
, user
, -1, STR_TERMINATE
); /* username */
331 p
+= clistr_push(cli
, p
, workgroup
, -1, STR_TERMINATE
); /* workgroup */
332 p
+= clistr_push(cli
, p
, "Unix", -1, STR_TERMINATE
);
333 p
+= clistr_push(cli
, p
, lanman
, -1, STR_TERMINATE
);
334 cli_setup_bcc(cli
, p
);
336 if (!cli_send_smb(cli
) || !cli_receive_smb(cli
)) {
337 return cli_nt_error(cli
);
340 show_msg(cli
->inbuf
);
342 if (cli_is_error(cli
)) {
343 return cli_nt_error(cli
);
346 cli
->vuid
= SVAL(cli
->inbuf
,smb_uid
);
347 p
= smb_buf(cli
->inbuf
);
348 p
+= clistr_pull(cli
->inbuf
, cli
->server_os
, p
, sizeof(fstring
),
350 p
+= clistr_pull(cli
->inbuf
, cli
->server_type
, p
, sizeof(fstring
),
352 p
+= clistr_pull(cli
->inbuf
, cli
->server_domain
, p
, sizeof(fstring
),
354 fstrcpy(cli
->user_name
, user
);
356 if (strstr(cli
->server_type
, "Samba")) {
357 cli
->is_samba
= True
;
363 /****************************************************************************
364 do a NT1 NTLM/LM encrypted session setup - for when extended security
366 @param cli client state to create do session setup on
368 @param pass *either* cleartext password (passlen !=24) or LM response.
369 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
370 @param workgroup The user's domain.
371 ****************************************************************************/
373 static NTSTATUS
cli_session_setup_nt1(struct cli_state
*cli
, const char *user
,
374 const char *pass
, size_t passlen
,
375 const char *ntpass
, size_t ntpasslen
,
376 const char *workgroup
)
378 uint32 capabilities
= cli_session_setup_capabilities(cli
);
379 DATA_BLOB lm_response
= data_blob_null
;
380 DATA_BLOB nt_response
= data_blob_null
;
381 DATA_BLOB session_key
= data_blob_null
;
386 /* do nothing - guest login */
387 } else if (passlen
!= 24) {
388 if (lp_client_ntlmv2_auth()) {
389 DATA_BLOB server_chal
;
390 DATA_BLOB names_blob
;
391 server_chal
= data_blob(cli
->secblob
.data
, MIN(cli
->secblob
.length
, 8));
393 /* note that the 'workgroup' here is a best guess - we don't know
394 the server's domain at this point. The 'server name' is also
397 names_blob
= NTLMv2_generate_names_blob(cli
->called
.name
, workgroup
);
399 if (!SMBNTLMv2encrypt(user
, workgroup
, pass
, &server_chal
,
401 &lm_response
, &nt_response
, &session_key
)) {
402 data_blob_free(&names_blob
);
403 data_blob_free(&server_chal
);
404 return NT_STATUS_ACCESS_DENIED
;
406 data_blob_free(&names_blob
);
407 data_blob_free(&server_chal
);
411 E_md4hash(pass
, nt_hash
);
414 nt_response
= data_blob_null
;
416 nt_response
= data_blob(NULL
, 24);
417 SMBNTencrypt(pass
,cli
->secblob
.data
,nt_response
.data
);
419 /* non encrypted password supplied. Ignore ntpass. */
420 if (lp_client_lanman_auth()) {
421 lm_response
= data_blob(NULL
, 24);
422 if (!SMBencrypt(pass
,cli
->secblob
.data
, lm_response
.data
)) {
423 /* Oops, the LM response is invalid, just put
424 the NT response there instead */
425 data_blob_free(&lm_response
);
426 lm_response
= data_blob(nt_response
.data
, nt_response
.length
);
429 /* LM disabled, place NT# in LM field instead */
430 lm_response
= data_blob(nt_response
.data
, nt_response
.length
);
433 session_key
= data_blob(NULL
, 16);
435 E_deshash(pass
, session_key
.data
);
436 memset(&session_key
.data
[8], '\0', 8);
438 SMBsesskeygen_ntv1(nt_hash
, NULL
, session_key
.data
);
442 cli_simple_set_signing(cli
, session_key
, lm_response
);
444 cli_simple_set_signing(cli
, session_key
, nt_response
);
447 /* pre-encrypted password supplied. Only used for
448 security=server, can't do
449 signing because we don't have original key */
451 lm_response
= data_blob(pass
, passlen
);
452 nt_response
= data_blob(ntpass
, ntpasslen
);
455 /* send a session setup command */
456 memset(cli
->outbuf
,'\0',smb_size
);
458 cli_set_message(cli
->outbuf
,13,0,True
);
459 SCVAL(cli
->outbuf
,smb_com
,SMBsesssetupX
);
460 cli_setup_packet(cli
);
462 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
463 SSVAL(cli
->outbuf
,smb_vwv2
,CLI_BUFFER_SIZE
);
464 SSVAL(cli
->outbuf
,smb_vwv3
,2);
465 SSVAL(cli
->outbuf
,smb_vwv4
,cli
->pid
);
466 SIVAL(cli
->outbuf
,smb_vwv5
,cli
->sesskey
);
467 SSVAL(cli
->outbuf
,smb_vwv7
,lm_response
.length
);
468 SSVAL(cli
->outbuf
,smb_vwv8
,nt_response
.length
);
469 SIVAL(cli
->outbuf
,smb_vwv11
,capabilities
);
470 p
= smb_buf(cli
->outbuf
);
471 if (lm_response
.length
) {
472 memcpy(p
,lm_response
.data
, lm_response
.length
); p
+= lm_response
.length
;
474 if (nt_response
.length
) {
475 memcpy(p
,nt_response
.data
, nt_response
.length
); p
+= nt_response
.length
;
477 p
+= clistr_push(cli
, p
, user
, -1, STR_TERMINATE
);
479 /* Upper case here might help some NTLMv2 implementations */
480 p
+= clistr_push(cli
, p
, workgroup
, -1, STR_TERMINATE
|STR_UPPER
);
481 p
+= clistr_push(cli
, p
, "Unix", -1, STR_TERMINATE
);
482 p
+= clistr_push(cli
, p
, "Samba", -1, STR_TERMINATE
);
483 cli_setup_bcc(cli
, p
);
485 if (!cli_send_smb(cli
) || !cli_receive_smb(cli
)) {
486 result
= cli_nt_error(cli
);
490 /* show_msg(cli->inbuf); */
492 if (cli_is_error(cli
)) {
493 result
= cli_nt_error(cli
);
497 /* use the returned vuid from now on */
498 cli
->vuid
= SVAL(cli
->inbuf
,smb_uid
);
500 p
= smb_buf(cli
->inbuf
);
501 p
+= clistr_pull(cli
->inbuf
, cli
->server_os
, p
, sizeof(fstring
),
503 p
+= clistr_pull(cli
->inbuf
, cli
->server_type
, p
, sizeof(fstring
),
505 p
+= clistr_pull(cli
->inbuf
, cli
->server_domain
, p
, sizeof(fstring
),
508 if (strstr(cli
->server_type
, "Samba")) {
509 cli
->is_samba
= True
;
512 fstrcpy(cli
->user_name
, user
);
514 if (session_key
.data
) {
515 /* Have plaintext orginal */
516 cli_set_session_key(cli
, session_key
);
519 result
= NT_STATUS_OK
;
521 data_blob_free(&lm_response
);
522 data_blob_free(&nt_response
);
523 data_blob_free(&session_key
);
527 /****************************************************************************
528 Send a extended security session setup blob
529 ****************************************************************************/
531 static bool cli_session_setup_blob_send(struct cli_state
*cli
, DATA_BLOB blob
)
533 uint32 capabilities
= cli_session_setup_capabilities(cli
);
536 capabilities
|= CAP_EXTENDED_SECURITY
;
538 /* send a session setup command */
539 memset(cli
->outbuf
,'\0',smb_size
);
541 cli_set_message(cli
->outbuf
,12,0,True
);
542 SCVAL(cli
->outbuf
,smb_com
,SMBsesssetupX
);
544 cli_setup_packet(cli
);
546 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
547 SSVAL(cli
->outbuf
,smb_vwv2
,CLI_BUFFER_SIZE
);
548 SSVAL(cli
->outbuf
,smb_vwv3
,2);
549 SSVAL(cli
->outbuf
,smb_vwv4
,1);
550 SIVAL(cli
->outbuf
,smb_vwv5
,0);
551 SSVAL(cli
->outbuf
,smb_vwv7
,blob
.length
);
552 SIVAL(cli
->outbuf
,smb_vwv10
,capabilities
);
553 p
= smb_buf(cli
->outbuf
);
554 memcpy(p
, blob
.data
, blob
.length
);
556 p
+= clistr_push(cli
, p
, "Unix", -1, STR_TERMINATE
);
557 p
+= clistr_push(cli
, p
, "Samba", -1, STR_TERMINATE
);
558 cli_setup_bcc(cli
, p
);
559 return cli_send_smb(cli
);
562 /****************************************************************************
563 Send a extended security session setup blob, returning a reply blob.
564 ****************************************************************************/
566 static DATA_BLOB
cli_session_setup_blob_receive(struct cli_state
*cli
)
568 DATA_BLOB blob2
= data_blob_null
;
572 if (!cli_receive_smb(cli
))
575 show_msg(cli
->inbuf
);
577 if (cli_is_error(cli
) && !NT_STATUS_EQUAL(cli_nt_error(cli
),
578 NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
582 /* use the returned vuid from now on */
583 cli
->vuid
= SVAL(cli
->inbuf
,smb_uid
);
585 p
= smb_buf(cli
->inbuf
);
587 blob2
= data_blob(p
, SVAL(cli
->inbuf
, smb_vwv3
));
590 p
+= clistr_pull(cli
->inbuf
, cli
->server_os
, p
, sizeof(fstring
),
593 /* w2k with kerberos doesn't properly null terminate this field */
594 len
= smb_bufrem(cli
->inbuf
, p
);
595 p
+= clistr_pull(cli
->inbuf
, cli
->server_type
, p
, sizeof(fstring
),
602 /****************************************************************************
603 Send a extended security session setup blob, returning a reply blob.
604 ****************************************************************************/
606 /* The following is calculated from :
608 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
609 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
613 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
615 static bool cli_session_setup_blob(struct cli_state
*cli
, DATA_BLOB blob
)
617 int32 remaining
= blob
.length
;
619 DATA_BLOB send_blob
= data_blob_null
;
620 int32 max_blob_size
= 0;
621 DATA_BLOB receive_blob
= data_blob_null
;
623 if (cli
->max_xmit
< BASE_SESSSETUP_BLOB_PACKET_SIZE
+ 1) {
624 DEBUG(0,("cli_session_setup_blob: cli->max_xmit too small "
625 "(was %u, need minimum %u)\n",
626 (unsigned int)cli
->max_xmit
,
627 BASE_SESSSETUP_BLOB_PACKET_SIZE
));
628 cli_set_nt_error(cli
, NT_STATUS_INVALID_PARAMETER
);
632 max_blob_size
= cli
->max_xmit
- BASE_SESSSETUP_BLOB_PACKET_SIZE
;
634 while ( remaining
> 0) {
635 if (remaining
>= max_blob_size
) {
636 send_blob
.length
= max_blob_size
;
637 remaining
-= max_blob_size
;
639 send_blob
.length
= remaining
;
643 send_blob
.data
= &blob
.data
[cur
];
644 cur
+= send_blob
.length
;
646 DEBUG(10, ("cli_session_setup_blob: Remaining (%u) sending (%u) current (%u)\n",
647 (unsigned int)remaining
,
648 (unsigned int)send_blob
.length
,
649 (unsigned int)cur
));
651 if (!cli_session_setup_blob_send(cli
, send_blob
)) {
652 DEBUG(0, ("cli_session_setup_blob: send failed\n"));
656 receive_blob
= cli_session_setup_blob_receive(cli
);
657 data_blob_free(&receive_blob
);
659 if (cli_is_error(cli
) &&
660 !NT_STATUS_EQUAL( cli_get_nt_error(cli
),
661 NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
662 DEBUG(0, ("cli_session_setup_blob: receive failed "
663 "(%s)\n", nt_errstr(cli_get_nt_error(cli
))));
672 /****************************************************************************
673 Use in-memory credentials cache
674 ****************************************************************************/
676 static void use_in_memory_ccache(void) {
677 setenv(KRB5_ENV_CCNAME
, "MEMORY:cliconnect", 1);
680 /****************************************************************************
681 Do a spnego/kerberos encrypted session setup.
682 ****************************************************************************/
684 static ADS_STATUS
cli_session_setup_kerberos(struct cli_state
*cli
, const char *principal
, const char *workgroup
)
686 DATA_BLOB negTokenTarg
;
687 DATA_BLOB session_key_krb5
;
691 cli_temp_set_signing(cli
);
693 DEBUG(2,("Doing kerberos session setup\n"));
695 /* generate the encapsulated kerberos5 ticket */
696 rc
= spnego_gen_negTokenTarg(principal
, 0, &negTokenTarg
, &session_key_krb5
, 0, NULL
);
699 DEBUG(1, ("cli_session_setup_kerberos: spnego_gen_negTokenTarg failed: %s\n",
701 return ADS_ERROR_KRB5(rc
);
705 file_save("negTokenTarg.dat", negTokenTarg
.data
, negTokenTarg
.length
);
708 if (!cli_session_setup_blob(cli
, negTokenTarg
)) {
709 nt_status
= cli_nt_error(cli
);
713 if (cli_is_error(cli
)) {
714 nt_status
= cli_nt_error(cli
);
715 if (NT_STATUS_IS_OK(nt_status
)) {
716 nt_status
= NT_STATUS_UNSUCCESSFUL
;
721 cli_set_session_key(cli
, session_key_krb5
);
723 if (cli_simple_set_signing(
724 cli
, session_key_krb5
, data_blob_null
)) {
726 /* 'resign' the last message, so we get the right sequence numbers
727 for checking the first reply from the server */
728 cli_calculate_sign_mac(cli
, cli
->outbuf
);
730 if (!cli_check_sign_mac(cli
, cli
->inbuf
)) {
731 nt_status
= NT_STATUS_ACCESS_DENIED
;
736 data_blob_free(&negTokenTarg
);
737 data_blob_free(&session_key_krb5
);
739 return ADS_ERROR_NT(NT_STATUS_OK
);
742 data_blob_free(&negTokenTarg
);
743 data_blob_free(&session_key_krb5
);
745 return ADS_ERROR_NT(nt_status
);
747 #endif /* HAVE_KRB5 */
750 /****************************************************************************
751 Do a spnego/NTLMSSP encrypted session setup.
752 ****************************************************************************/
754 static NTSTATUS
cli_session_setup_ntlmssp(struct cli_state
*cli
, const char *user
,
755 const char *pass
, const char *domain
)
757 struct ntlmssp_state
*ntlmssp_state
;
761 DATA_BLOB blob
= data_blob_null
;
762 DATA_BLOB blob_in
= data_blob_null
;
763 DATA_BLOB blob_out
= data_blob_null
;
765 cli_temp_set_signing(cli
);
767 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_client_start(&ntlmssp_state
))) {
770 ntlmssp_want_feature(ntlmssp_state
, NTLMSSP_FEATURE_SESSION_KEY
);
772 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_username(ntlmssp_state
, user
))) {
775 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_domain(ntlmssp_state
, domain
))) {
778 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_password(ntlmssp_state
, pass
))) {
783 nt_status
= ntlmssp_update(ntlmssp_state
,
785 data_blob_free(&blob_in
);
786 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) || NT_STATUS_IS_OK(nt_status
)) {
788 /* and wrap it in a SPNEGO wrapper */
789 msg1
= gen_negTokenInit(OID_NTLMSSP
, blob_out
);
791 /* wrap it in SPNEGO */
792 msg1
= spnego_gen_auth(blob_out
);
795 /* now send that blob on its way */
796 if (!cli_session_setup_blob_send(cli
, msg1
)) {
797 DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
798 nt_status
= NT_STATUS_UNSUCCESSFUL
;
800 blob
= cli_session_setup_blob_receive(cli
);
802 nt_status
= cli_nt_error(cli
);
803 if (cli_is_error(cli
) && NT_STATUS_IS_OK(nt_status
)) {
804 if (cli
->smb_rw_error
== SMB_READ_BAD_SIG
) {
805 nt_status
= NT_STATUS_ACCESS_DENIED
;
807 nt_status
= NT_STATUS_UNSUCCESSFUL
;
811 data_blob_free(&msg1
);
815 if (NT_STATUS_IS_OK(nt_status
)) {
816 nt_status
= NT_STATUS_UNSUCCESSFUL
;
818 } else if ((turn
== 1) &&
819 NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
820 DATA_BLOB tmp_blob
= data_blob_null
;
821 /* the server might give us back two challenges */
822 if (!spnego_parse_challenge(blob
, &blob_in
,
824 DEBUG(3,("Failed to parse challenges\n"));
825 nt_status
= NT_STATUS_INVALID_PARAMETER
;
827 data_blob_free(&tmp_blob
);
829 if (!spnego_parse_auth_response(blob
, nt_status
, OID_NTLMSSP
,
831 DEBUG(3,("Failed to parse auth response\n"));
832 if (NT_STATUS_IS_OK(nt_status
)
833 || NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
))
834 nt_status
= NT_STATUS_INVALID_PARAMETER
;
837 data_blob_free(&blob
);
838 data_blob_free(&blob_out
);
840 } while (NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
));
842 data_blob_free(&blob_in
);
844 if (NT_STATUS_IS_OK(nt_status
)) {
846 fstrcpy(cli
->server_domain
, ntlmssp_state
->server_domain
);
847 cli_set_session_key(cli
, ntlmssp_state
->session_key
);
849 if (cli_simple_set_signing(
850 cli
, ntlmssp_state
->session_key
, data_blob_null
)) {
852 /* 'resign' the last message, so we get the right sequence numbers
853 for checking the first reply from the server */
854 cli_calculate_sign_mac(cli
, cli
->outbuf
);
856 if (!cli_check_sign_mac(cli
, cli
->inbuf
)) {
857 nt_status
= NT_STATUS_ACCESS_DENIED
;
862 /* we have a reference conter on ntlmssp_state, if we are signing
863 then the state will be kept by the signing engine */
865 ntlmssp_end(&ntlmssp_state
);
867 if (!NT_STATUS_IS_OK(nt_status
)) {
873 /****************************************************************************
874 Do a spnego encrypted session setup.
876 user_domain: The shortname of the domain the user/machine is a member of.
877 dest_realm: The realm we're connecting to, if NULL we use our default realm.
878 ****************************************************************************/
880 ADS_STATUS
cli_session_setup_spnego(struct cli_state
*cli
, const char *user
,
881 const char *pass
, const char *user_domain
,
882 const char * dest_realm
)
884 char *principal
= NULL
;
885 char *OIDs
[ASN1_MAX_OIDS
];
888 const char *p
= NULL
;
889 char *account
= NULL
;
891 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli
->secblob
.length
));
893 /* the server might not even do spnego */
894 if (cli
->secblob
.length
<= 16) {
895 DEBUG(3,("server didn't supply a full spnego negprot\n"));
900 file_save("negprot.dat", cli
->secblob
.data
, cli
->secblob
.length
);
903 /* there is 16 bytes of GUID before the real spnego packet starts */
904 blob
= data_blob(cli
->secblob
.data
+16, cli
->secblob
.length
-16);
906 /* The server sent us the first part of the SPNEGO exchange in the
907 * negprot reply. It is WRONG to depend on the principal sent in the
908 * negprot reply, but right now we do it. If we don't receive one,
909 * we try to best guess, then fall back to NTLM. */
910 if (!spnego_parse_negTokenInit(blob
, OIDs
, &principal
)) {
911 data_blob_free(&blob
);
912 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
914 data_blob_free(&blob
);
916 /* make sure the server understands kerberos */
917 for (i
=0;OIDs
[i
];i
++) {
918 DEBUG(3,("got OID=%s\n", OIDs
[i
]));
919 if (strcmp(OIDs
[i
], OID_KERBEROS5_OLD
) == 0 ||
920 strcmp(OIDs
[i
], OID_KERBEROS5
) == 0) {
921 cli
->got_kerberos_mechanism
= True
;
923 talloc_free(OIDs
[i
]);
926 DEBUG(3,("got principal=%s\n", principal
? principal
: "<null>"));
928 fstrcpy(cli
->user_name
, user
);
931 /* If password is set we reauthenticate to kerberos server
932 * and do not store results */
934 if (cli
->got_kerberos_mechanism
&& cli
->use_kerberos
) {
940 use_in_memory_ccache();
941 ret
= kerberos_kinit_password(user
, pass
, 0 /* no time correction for now */, NULL
);
944 TALLOC_FREE(principal
);
945 DEBUG(0, ("Kinit failed: %s\n", error_message(ret
)));
946 if (cli
->fallback_after_kerberos
)
948 return ADS_ERROR_KRB5(ret
);
952 /* If we get a bad principal, try to guess it if
953 we have a valid host NetBIOS name.
955 if (strequal(principal
, ADS_IGNORE_PRINCIPAL
)) {
956 TALLOC_FREE(principal
);
959 if (principal
== NULL
&&
960 !is_ipaddress(cli
->desthost
) &&
961 !strequal(STAR_SMBSERVER
,
964 char *machine
= NULL
;
966 DEBUG(3,("cli_session_setup_spnego: got a "
967 "bad server principal, trying to guess ...\n"));
969 host
= strchr_m(cli
->desthost
, '.');
971 machine
= SMB_STRNDUP(cli
->desthost
,
972 host
- cli
->desthost
);
974 machine
= SMB_STRDUP(cli
->desthost
);
976 if (machine
== NULL
) {
977 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
981 realm
= SMB_STRDUP(dest_realm
);
984 realm
= kerberos_get_default_realm_from_ccache();
986 if (realm
&& *realm
) {
987 principal
= talloc_asprintf(NULL
, "%s$@%s",
992 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
994 DEBUG(3,("cli_session_setup_spnego: guessed "
995 "server principal=%s\n",
996 principal
? principal
: "<null>"));
1003 rc
= cli_session_setup_kerberos(cli
, principal
,
1005 if (ADS_ERR_OK(rc
) || !cli
->fallback_after_kerberos
) {
1006 TALLOC_FREE(principal
);
1013 TALLOC_FREE(principal
);
1017 account
= talloc_strdup(talloc_tos(), user
);
1019 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
1022 /* when falling back to ntlmssp while authenticating with a machine
1023 * account strip off the realm - gd */
1025 if ((p
= strchr_m(user
, '@')) != NULL
) {
1026 account
[PTR_DIFF(p
,user
)] = '\0';
1029 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli
, account
, pass
, user_domain
));
1032 /****************************************************************************
1033 Send a session setup. The username and workgroup is in UNIX character
1034 format and must be converted to DOS codepage format before sending. If the
1035 password is in plaintext, the same should be done.
1036 ****************************************************************************/
1038 NTSTATUS
cli_session_setup(struct cli_state
*cli
,
1040 const char *pass
, int passlen
,
1041 const char *ntpass
, int ntpasslen
,
1042 const char *workgroup
)
1048 fstrcpy(user2
, user
);
1057 /* allow for workgroups as part of the username */
1058 if ((p
=strchr_m(user2
,'\\')) || (p
=strchr_m(user2
,'/')) ||
1059 (p
=strchr_m(user2
,*lp_winbind_separator()))) {
1065 if (cli
->protocol
< PROTOCOL_LANMAN1
) {
1066 return NT_STATUS_OK
;
1069 /* now work out what sort of session setup we are going to
1070 do. I have split this into separate functions to make the
1071 flow a bit easier to understand (tridge) */
1073 /* if its an older server then we have to use the older request format */
1075 if (cli
->protocol
< PROTOCOL_NT1
) {
1076 if (!lp_client_lanman_auth() && passlen
!= 24 && (*pass
)) {
1077 DEBUG(1, ("Server requested LM password but 'client lanman auth'"
1079 return NT_STATUS_ACCESS_DENIED
;
1082 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) == 0 &&
1083 !lp_client_plaintext_auth() && (*pass
)) {
1084 DEBUG(1, ("Server requested plaintext password but "
1085 "'client plaintext auth' is disabled\n"));
1086 return NT_STATUS_ACCESS_DENIED
;
1089 return cli_session_setup_lanman2(cli
, user
, pass
, passlen
,
1093 /* if no user is supplied then we have to do an anonymous connection.
1094 passwords are ignored */
1096 if (!user
|| !*user
)
1097 return cli_session_setup_guest(cli
);
1099 /* if the server is share level then send a plaintext null
1100 password at this point. The password is sent in the tree
1103 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
) == 0)
1104 return cli_session_setup_plaintext(cli
, user
, "", workgroup
);
1106 /* if the server doesn't support encryption then we have to use
1107 plaintext. The second password is ignored */
1109 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) == 0) {
1110 if (!lp_client_plaintext_auth() && (*pass
)) {
1111 DEBUG(1, ("Server requested plaintext password but "
1112 "'client plaintext auth' is disabled\n"));
1113 return NT_STATUS_ACCESS_DENIED
;
1115 return cli_session_setup_plaintext(cli
, user
, pass
, workgroup
);
1118 /* if the server supports extended security then use SPNEGO */
1120 if (cli
->capabilities
& CAP_EXTENDED_SECURITY
) {
1121 ADS_STATUS status
= cli_session_setup_spnego(cli
, user
, pass
,
1123 if (!ADS_ERR_OK(status
)) {
1124 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status
)));
1125 return ads_ntstatus(status
);
1130 /* otherwise do a NT1 style session setup */
1131 status
= cli_session_setup_nt1(cli
, user
, pass
, passlen
,
1132 ntpass
, ntpasslen
, workgroup
);
1133 if (!NT_STATUS_IS_OK(status
)) {
1134 DEBUG(3,("cli_session_setup: NT1 session setup "
1135 "failed: %s\n", nt_errstr(status
)));
1140 if (strstr(cli
->server_type
, "Samba")) {
1141 cli
->is_samba
= True
;
1144 return NT_STATUS_OK
;
1147 /****************************************************************************
1149 *****************************************************************************/
1151 bool cli_ulogoff(struct cli_state
*cli
)
1153 memset(cli
->outbuf
,'\0',smb_size
);
1154 cli_set_message(cli
->outbuf
,2,0,True
);
1155 SCVAL(cli
->outbuf
,smb_com
,SMBulogoffX
);
1156 cli_setup_packet(cli
);
1157 SSVAL(cli
->outbuf
,smb_vwv0
,0xFF);
1158 SSVAL(cli
->outbuf
,smb_vwv2
,0); /* no additional info */
1161 if (!cli_receive_smb(cli
))
1164 if (cli_is_error(cli
)) {
1172 /****************************************************************************
1174 ****************************************************************************/
1176 struct async_req
*cli_tcon_andx_send(TALLOC_CTX
*mem_ctx
,
1177 struct event_context
*ev
,
1178 struct cli_state
*cli
,
1179 const char *share
, const char *dev
,
1180 const char *pass
, int passlen
)
1184 struct async_req
*result
;
1188 fstrcpy(cli
->share
, share
);
1190 /* in user level security don't send a password now */
1191 if (cli
->sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
) {
1194 } else if (pass
== NULL
) {
1195 DEBUG(1, ("Server not using user level security and no "
1196 "password supplied.\n"));
1200 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) &&
1201 *pass
&& passlen
!= 24) {
1202 if (!lp_client_lanman_auth()) {
1203 DEBUG(1, ("Server requested LANMAN password "
1204 "(share-level security) but "
1205 "'client lanman auth' is disabled\n"));
1210 * Non-encrypted passwords - convert to DOS codepage before
1214 SMBencrypt(pass
, cli
->secblob
.data
, (uchar
*)pword
);
1216 if((cli
->sec_mode
& (NEGOTIATE_SECURITY_USER_LEVEL
1217 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
))
1219 if (!lp_client_plaintext_auth() && (*pass
)) {
1220 DEBUG(1, ("Server requested plaintext "
1221 "password but 'client plaintext "
1222 "auth' is disabled\n"));
1227 * Non-encrypted passwords - convert to DOS codepage
1230 passlen
= clistr_push(cli
, pword
, pass
, sizeof(pword
),
1232 if (passlen
== -1) {
1233 DEBUG(1, ("clistr_push(pword) failed\n"));
1238 memcpy(pword
, pass
, passlen
);
1243 SCVAL(vwv
+0, 0, 0xFF);
1246 SSVAL(vwv
+2, 0, TCONX_FLAG_EXTENDED_RESPONSE
);
1247 SSVAL(vwv
+3, 0, passlen
);
1250 bytes
= (uint8_t *)talloc_memdup(talloc_tos(), pword
, passlen
);
1252 bytes
= talloc_array(talloc_tos(), uint8_t, 0);
1258 tmp
= talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1259 cli
->desthost
, share
);
1264 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), tmp
, strlen(tmp
)+1,
1269 * Add the devicetype
1271 tmp
= talloc_strdup_upper(talloc_tos(), dev
);
1276 bytes
= smb_bytes_push_str(bytes
, false, tmp
, strlen(tmp
)+1, NULL
);
1279 if (bytes
== NULL
) {
1283 result
= cli_request_send(mem_ctx
, ev
, cli
, SMBtconX
, 0,
1284 4, vwv
, 0, talloc_get_size(bytes
), bytes
);
1289 result
= async_req_new(mem_ctx
);
1290 if (async_post_ntstatus(result
, ev
, NT_STATUS_ACCESS_DENIED
)) {
1293 TALLOC_FREE(result
);
1297 NTSTATUS
cli_tcon_andx_recv(struct async_req
*req
)
1299 struct cli_request
*cli_req
= talloc_get_type_abort(
1300 req
->private_data
, struct cli_request
);
1301 struct cli_state
*cli
= cli_req
->cli
;
1308 if (async_req_is_nterror(req
, &status
)) {
1312 status
= cli_pull_reply(req
, &wct
, &vwv
, &num_bytes
, &bytes
);
1313 if (!NT_STATUS_IS_OK(status
)) {
1317 clistr_pull(cli_req
->inbuf
, cli
->dev
, bytes
, sizeof(fstring
),
1318 num_bytes
, STR_TERMINATE
|STR_ASCII
);
1320 if ((cli
->protocol
>= PROTOCOL_NT1
) && (num_bytes
== 3)) {
1321 /* almost certainly win95 - enable bug fixes */
1326 * Make sure that we have the optional support 16-bit field. WCT > 2.
1327 * Avoids issues when connecting to Win9x boxes sharing files
1330 cli
->dfsroot
= false;
1332 if ((wct
> 2) && (cli
->protocol
>= PROTOCOL_LANMAN2
)) {
1333 cli
->dfsroot
= ((SVAL(vwv
+2, 0) & SMB_SHARE_IN_DFS
) != 0);
1336 cli
->cnum
= SVAL(cli_req
->inbuf
,smb_tid
);
1337 return NT_STATUS_OK
;
1340 NTSTATUS
cli_tcon_andx(struct cli_state
*cli
, const char *share
,
1341 const char *dev
, const char *pass
, int passlen
)
1343 TALLOC_CTX
*frame
= talloc_stackframe();
1344 struct event_context
*ev
;
1345 struct async_req
*req
;
1348 if (cli
->fd_event
!= NULL
) {
1350 * Can't use sync call while an async call is in flight
1352 status
= NT_STATUS_INVALID_PARAMETER
;
1356 ev
= event_context_init(frame
);
1358 status
= NT_STATUS_NO_MEMORY
;
1362 req
= cli_tcon_andx_send(frame
, ev
, cli
, share
, dev
, pass
, passlen
);
1364 status
= NT_STATUS_NO_MEMORY
;
1368 while (req
->state
< ASYNC_REQ_DONE
) {
1369 event_loop_once(ev
);
1372 status
= cli_tcon_andx_recv(req
);
1378 /****************************************************************************
1379 Send a tree disconnect.
1380 ****************************************************************************/
1382 bool cli_tdis(struct cli_state
*cli
)
1384 memset(cli
->outbuf
,'\0',smb_size
);
1385 cli_set_message(cli
->outbuf
,0,0,True
);
1386 SCVAL(cli
->outbuf
,smb_com
,SMBtdis
);
1387 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
1388 cli_setup_packet(cli
);
1391 if (!cli_receive_smb(cli
))
1394 if (cli_is_error(cli
)) {
1402 /****************************************************************************
1403 Send a negprot command.
1404 ****************************************************************************/
1406 void cli_negprot_sendsync(struct cli_state
*cli
)
1411 if (cli
->protocol
< PROTOCOL_NT1
)
1412 cli
->use_spnego
= False
;
1414 memset(cli
->outbuf
,'\0',smb_size
);
1416 /* setup the protocol strings */
1417 cli_set_message(cli
->outbuf
,0,0,True
);
1419 p
= smb_buf(cli
->outbuf
);
1420 for (numprots
=0; numprots
< ARRAY_SIZE(prots
); numprots
++) {
1421 if (prots
[numprots
].prot
> cli
->protocol
) {
1425 p
+= clistr_push(cli
, p
, prots
[numprots
].name
, -1, STR_TERMINATE
);
1428 SCVAL(cli
->outbuf
,smb_com
,SMBnegprot
);
1429 cli_setup_bcc(cli
, p
);
1430 cli_setup_packet(cli
);
1432 SCVAL(smb_buf(cli
->outbuf
),0,2);
1437 /****************************************************************************
1438 Send a negprot command.
1439 ****************************************************************************/
1441 struct async_req
*cli_negprot_send(TALLOC_CTX
*mem_ctx
,
1442 struct event_context
*ev
,
1443 struct cli_state
*cli
)
1445 struct async_req
*result
;
1446 uint8_t *bytes
= NULL
;
1449 if (cli
->protocol
< PROTOCOL_NT1
)
1450 cli
->use_spnego
= False
;
1452 /* setup the protocol strings */
1453 for (numprots
=0; numprots
< ARRAY_SIZE(prots
); numprots
++) {
1455 if (prots
[numprots
].prot
> cli
->protocol
) {
1458 bytes
= (uint8_t *)talloc_append_blob(
1459 talloc_tos(), bytes
, data_blob_const(&c
, sizeof(c
)));
1460 if (bytes
== NULL
) {
1463 bytes
= smb_bytes_push_str(bytes
, false,
1464 prots
[numprots
].name
,
1465 strlen(prots
[numprots
].name
)+1,
1467 if (bytes
== NULL
) {
1472 result
= cli_request_send(mem_ctx
, ev
, cli
, SMBnegprot
, 0, 0, NULL
, 0,
1473 talloc_get_size(bytes
), bytes
);
1478 NTSTATUS
cli_negprot_recv(struct async_req
*req
)
1480 struct cli_request
*cli_req
= talloc_get_type_abort(
1481 req
->private_data
, struct cli_request
);
1482 struct cli_state
*cli
= cli_req
->cli
;
1490 if (async_req_is_nterror(req
, &status
)) {
1494 status
= cli_pull_reply(req
, &wct
, &vwv
, &num_bytes
, &bytes
);
1495 if (!NT_STATUS_IS_OK(status
)) {
1499 protnum
= SVAL(vwv
, 0);
1501 if ((protnum
>= ARRAY_SIZE(prots
))
1502 || (prots
[protnum
].prot
> cli_req
->cli
->protocol
)) {
1503 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
1506 cli
->protocol
= prots
[protnum
].prot
;
1508 if ((cli
->protocol
< PROTOCOL_NT1
) && cli
->sign_info
.mandatory_signing
) {
1509 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1510 return NT_STATUS_ACCESS_DENIED
;
1513 if (cli
->protocol
>= PROTOCOL_NT1
) {
1516 cli
->sec_mode
= CVAL(vwv
+ 1, 0);
1517 cli
->max_mux
= SVAL(vwv
+ 1, 1);
1518 cli
->max_xmit
= IVAL(vwv
+ 3, 1);
1519 cli
->sesskey
= IVAL(vwv
+ 7, 1);
1520 cli
->serverzone
= SVALS(vwv
+ 15, 1);
1521 cli
->serverzone
*= 60;
1522 /* this time arrives in real GMT */
1523 ts
= interpret_long_date(((char *)(vwv
+11))+1);
1524 cli
->servertime
= ts
.tv_sec
;
1525 cli
->secblob
= data_blob(bytes
, num_bytes
);
1526 cli
->capabilities
= IVAL(vwv
+ 9, 1);
1527 if (cli
->capabilities
& CAP_RAW_MODE
) {
1528 cli
->readbraw_supported
= True
;
1529 cli
->writebraw_supported
= True
;
1531 /* work out if they sent us a workgroup */
1532 if (!(cli
->capabilities
& CAP_EXTENDED_SECURITY
) &&
1533 smb_buflen(cli
->inbuf
) > 8) {
1534 clistr_pull(cli
->inbuf
, cli
->server_domain
,
1535 bytes
+8, sizeof(cli
->server_domain
),
1537 STR_UNICODE
|STR_NOALIGN
);
1541 * As signing is slow we only turn it on if either the client or
1542 * the server require it. JRA.
1545 if (cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_REQUIRED
) {
1546 /* Fail if server says signing is mandatory and we don't want to support it. */
1547 if (!cli
->sign_info
.allow_smb_signing
) {
1548 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1549 return NT_STATUS_ACCESS_DENIED
;
1551 cli
->sign_info
.negotiated_smb_signing
= True
;
1552 cli
->sign_info
.mandatory_signing
= True
;
1553 } else if (cli
->sign_info
.mandatory_signing
&& cli
->sign_info
.allow_smb_signing
) {
1554 /* Fail if client says signing is mandatory and the server doesn't support it. */
1555 if (!(cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_ENABLED
)) {
1556 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1557 return NT_STATUS_ACCESS_DENIED
;
1559 cli
->sign_info
.negotiated_smb_signing
= True
;
1560 cli
->sign_info
.mandatory_signing
= True
;
1561 } else if (cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_ENABLED
) {
1562 cli
->sign_info
.negotiated_smb_signing
= True
;
1565 if (cli
->capabilities
& (CAP_LARGE_READX
|CAP_LARGE_WRITEX
)) {
1566 SAFE_FREE(cli
->outbuf
);
1567 SAFE_FREE(cli
->inbuf
);
1568 cli
->outbuf
= (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE
+LARGE_WRITEX_HDR_SIZE
+SAFETY_MARGIN
);
1569 cli
->inbuf
= (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE
+LARGE_WRITEX_HDR_SIZE
+SAFETY_MARGIN
);
1570 cli
->bufsize
= CLI_SAMBA_MAX_LARGE_READX_SIZE
+ LARGE_WRITEX_HDR_SIZE
;
1573 } else if (cli
->protocol
>= PROTOCOL_LANMAN1
) {
1574 cli
->use_spnego
= False
;
1575 cli
->sec_mode
= SVAL(vwv
+ 1, 0);
1576 cli
->max_xmit
= SVAL(vwv
+ 2, 0);
1577 cli
->max_mux
= SVAL(vwv
+ 3, 0);
1578 cli
->sesskey
= IVAL(vwv
+ 6, 0);
1579 cli
->serverzone
= SVALS(vwv
+ 10, 0);
1580 cli
->serverzone
*= 60;
1581 /* this time is converted to GMT by make_unix_date */
1582 cli
->servertime
= cli_make_unix_date(
1583 cli
, (char *)(vwv
+ 8));
1584 cli
->readbraw_supported
= ((SVAL(vwv
+ 5, 0) & 0x1) != 0);
1585 cli
->writebraw_supported
= ((SVAL(vwv
+ 5, 0) & 0x2) != 0);
1586 cli
->secblob
= data_blob(bytes
, num_bytes
);
1588 /* the old core protocol */
1589 cli
->use_spnego
= False
;
1591 cli
->serverzone
= get_time_zone(time(NULL
));
1594 cli
->max_xmit
= MIN(cli
->max_xmit
, CLI_BUFFER_SIZE
);
1596 /* a way to force ascii SMB */
1597 if (getenv("CLI_FORCE_ASCII"))
1598 cli
->capabilities
&= ~CAP_UNICODE
;
1600 return NT_STATUS_OK
;
1603 NTSTATUS
cli_negprot(struct cli_state
*cli
)
1605 TALLOC_CTX
*frame
= talloc_stackframe();
1606 struct event_context
*ev
;
1607 struct async_req
*req
;
1608 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1610 if (cli
->fd_event
!= NULL
) {
1612 * Can't use sync call while an async call is in flight
1614 cli_set_error(cli
, NT_STATUS_INVALID_PARAMETER
);
1618 ev
= event_context_init(frame
);
1623 req
= cli_negprot_send(frame
, ev
, cli
);
1628 while (req
->state
< ASYNC_REQ_DONE
) {
1629 event_loop_once(ev
);
1632 status
= cli_negprot_recv(req
);
1638 /****************************************************************************
1639 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1640 ****************************************************************************/
1642 bool cli_session_request(struct cli_state
*cli
,
1643 struct nmb_name
*calling
, struct nmb_name
*called
)
1648 /* 445 doesn't have session request */
1649 if (cli
->port
== 445)
1652 memcpy(&(cli
->calling
), calling
, sizeof(*calling
));
1653 memcpy(&(cli
->called
), called
, sizeof(*called
));
1655 /* put in the destination name */
1656 p
= cli
->outbuf
+len
;
1657 name_mangle(cli
->called
.name
, p
, cli
->called
.name_type
);
1661 p
= cli
->outbuf
+len
;
1662 name_mangle(cli
->calling
.name
, p
, cli
->calling
.name_type
);
1665 /* send a session request (RFC 1002) */
1666 /* setup the packet length
1667 * Remove four bytes from the length count, since the length
1668 * field in the NBT Session Service header counts the number
1669 * of bytes which follow. The cli_send_smb() function knows
1670 * about this and accounts for those four bytes.
1674 _smb_setlen(cli
->outbuf
,len
);
1675 SCVAL(cli
->outbuf
,0,0x81);
1678 DEBUG(5,("Sent session request\n"));
1680 if (!cli_receive_smb(cli
))
1683 if (CVAL(cli
->inbuf
,0) == 0x84) {
1684 /* C. Hoch 9/14/95 Start */
1685 /* For information, here is the response structure.
1686 * We do the byte-twiddling to for portability.
1687 struct RetargetResponse{
1689 unsigned char flags;
1695 uint16_t port
= (CVAL(cli
->inbuf
,8)<<8)+CVAL(cli
->inbuf
,9);
1696 struct in_addr dest_ip
;
1699 /* SESSION RETARGET */
1700 putip((char *)&dest_ip
,cli
->inbuf
+4);
1701 in_addr_to_sockaddr_storage(&cli
->dest_ss
, dest_ip
);
1703 status
= open_socket_out(&cli
->dest_ss
, port
,
1704 LONG_CONNECT_TIMEOUT
, &cli
->fd
);
1705 if (!NT_STATUS_IS_OK(status
)) {
1709 DEBUG(3,("Retargeted\n"));
1711 set_socket_options(cli
->fd
, lp_socket_options());
1718 DEBUG(0,("Retarget recursion - failing\n"));
1722 ret
= cli_session_request(cli
, calling
, called
);
1726 } /* C. Hoch 9/14/95 End */
1728 if (CVAL(cli
->inbuf
,0) != 0x82) {
1729 /* This is the wrong place to put the error... JRA. */
1730 cli
->rap_error
= CVAL(cli
->inbuf
,4);
1736 static void smb_sock_connected(struct async_req
*req
)
1738 int *pfd
= (int *)req
->async
.priv
;
1742 status
= open_socket_out_defer_recv(req
, &fd
);
1743 if (NT_STATUS_IS_OK(status
)) {
1748 static NTSTATUS
open_smb_socket(const struct sockaddr_storage
*pss
,
1749 uint16_t *port
, int timeout
, int *pfd
)
1751 struct event_context
*ev
;
1752 struct async_req
*r139
, *r445
;
1758 return open_socket_out(pss
, *port
, timeout
, pfd
);
1761 ev
= event_context_init(talloc_tos());
1763 return NT_STATUS_NO_MEMORY
;
1766 r445
= open_socket_out_defer_send(ev
, ev
, timeval_set(0, 0),
1768 r139
= open_socket_out_defer_send(ev
, ev
, timeval_set(0, 3000),
1770 if ((r445
== NULL
) || (r139
== NULL
)) {
1771 status
= NT_STATUS_NO_MEMORY
;
1774 r445
->async
.fn
= smb_sock_connected
;
1775 r445
->async
.priv
= &fd445
;
1776 r139
->async
.fn
= smb_sock_connected
;
1777 r139
->async
.priv
= &fd139
;
1779 while ((fd139
== -1) && (r139
->state
< ASYNC_REQ_DONE
)
1780 && (fd445
== -1) && (r445
->state
< ASYNC_REQ_DONE
)) {
1781 event_loop_once(ev
);
1784 if ((fd139
!= -1) && (fd445
!= -1)) {
1792 status
= NT_STATUS_OK
;
1798 status
= NT_STATUS_OK
;
1802 status
= open_socket_out_defer_recv(r445
, &fd445
);
1808 /****************************************************************************
1809 Open the client sockets.
1810 ****************************************************************************/
1812 NTSTATUS
cli_connect(struct cli_state
*cli
,
1814 struct sockaddr_storage
*dest_ss
)
1817 int name_type
= 0x20;
1818 TALLOC_CTX
*frame
= talloc_stackframe();
1819 unsigned int num_addrs
= 0;
1821 struct sockaddr_storage
*ss_arr
= NULL
;
1824 /* reasonable default hostname */
1826 host
= STAR_SMBSERVER
;
1829 fstrcpy(cli
->desthost
, host
);
1831 /* allow hostnames of the form NAME#xx and do a netbios lookup */
1832 if ((p
= strchr(cli
->desthost
, '#'))) {
1833 name_type
= strtol(p
+1, NULL
, 16);
1837 if (!dest_ss
|| is_zero_addr((struct sockaddr
*)dest_ss
)) {
1838 NTSTATUS status
=resolve_name_list(frame
,
1843 if (!NT_STATUS_IS_OK(status
)) {
1845 return NT_STATUS_BAD_NETWORK_NAME
;
1849 ss_arr
= TALLOC_P(frame
, struct sockaddr_storage
);
1852 return NT_STATUS_NO_MEMORY
;
1857 for (i
= 0; i
< num_addrs
; i
++) {
1858 cli
->dest_ss
= ss_arr
[i
];
1859 if (getenv("LIBSMB_PROG")) {
1860 cli
->fd
= sock_exec(getenv("LIBSMB_PROG"));
1862 uint16_t port
= cli
->port
;
1864 status
= open_smb_socket(&cli
->dest_ss
, &port
,
1865 cli
->timeout
, &cli
->fd
);
1866 if (NT_STATUS_IS_OK(status
)) {
1870 if (cli
->fd
== -1) {
1871 char addr
[INET6_ADDRSTRLEN
];
1872 print_sockaddr(addr
, sizeof(addr
), &ss_arr
[i
]);
1873 DEBUG(2,("Error connecting to %s (%s)\n",
1874 dest_ss
?addr
:host
,strerror(errno
)));
1876 /* Exit from loop on first connection. */
1881 if (cli
->fd
== -1) {
1883 return map_nt_error_from_unix(errno
);
1887 *dest_ss
= cli
->dest_ss
;
1890 set_socket_options(cli
->fd
, lp_socket_options());
1893 return NT_STATUS_OK
;
1897 establishes a connection to after the negprot.
1898 @param output_cli A fully initialised cli structure, non-null only on success
1899 @param dest_host The netbios name of the remote host
1900 @param dest_ss (optional) The the destination IP, NULL for name based lookup
1901 @param port (optional) The destination port (0 for default)
1902 @param retry bool. Did this connection fail with a retryable error ?
1905 NTSTATUS
cli_start_connection(struct cli_state
**output_cli
,
1906 const char *my_name
,
1907 const char *dest_host
,
1908 struct sockaddr_storage
*dest_ss
, int port
,
1909 int signing_state
, int flags
,
1913 struct nmb_name calling
;
1914 struct nmb_name called
;
1915 struct cli_state
*cli
;
1916 struct sockaddr_storage ss
;
1922 my_name
= global_myname();
1924 if (!(cli
= cli_initialise())) {
1925 return NT_STATUS_NO_MEMORY
;
1928 make_nmb_name(&calling
, my_name
, 0x0);
1929 make_nmb_name(&called
, dest_host
, 0x20);
1931 cli_set_port(cli
, port
);
1932 cli_set_timeout(cli
, 10000); /* 10 seconds. */
1942 DEBUG(3,("Connecting to host=%s\n", dest_host
));
1944 nt_status
= cli_connect(cli
, dest_host
, &ss
);
1945 if (!NT_STATUS_IS_OK(nt_status
)) {
1946 char addr
[INET6_ADDRSTRLEN
];
1947 print_sockaddr(addr
, sizeof(addr
), &ss
);
1948 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
1949 nmb_namestr(&called
), addr
, nt_errstr(nt_status
) ));
1957 if (!cli_session_request(cli
, &calling
, &called
)) {
1959 DEBUG(1,("session request to %s failed (%s)\n",
1960 called
.name
, cli_errstr(cli
)));
1961 if ((p
=strchr(called
.name
, '.')) && !is_ipaddress(called
.name
)) {
1965 if (strcmp(called
.name
, STAR_SMBSERVER
)) {
1966 make_nmb_name(&called
, STAR_SMBSERVER
, 0x20);
1969 return NT_STATUS_BAD_NETWORK_NAME
;
1972 cli_setup_signing_state(cli
, signing_state
);
1974 if (flags
& CLI_FULL_CONNECTION_DONT_SPNEGO
)
1975 cli
->use_spnego
= False
;
1976 else if (flags
& CLI_FULL_CONNECTION_USE_KERBEROS
)
1977 cli
->use_kerberos
= True
;
1979 if ((flags
& CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS
) &&
1980 cli
->use_kerberos
) {
1981 cli
->fallback_after_kerberos
= true;
1984 nt_status
= cli_negprot(cli
);
1985 if (!NT_STATUS_IS_OK(nt_status
)) {
1986 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status
)));
1992 return NT_STATUS_OK
;
1997 establishes a connection right up to doing tconX, password specified.
1998 @param output_cli A fully initialised cli structure, non-null only on success
1999 @param dest_host The netbios name of the remote host
2000 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2001 @param port (optional) The destination port (0 for default)
2002 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2003 @param service_type The 'type' of serivice.
2004 @param user Username, unix string
2005 @param domain User's domain
2006 @param password User's password, unencrypted unix string.
2007 @param retry bool. Did this connection fail with a retryable error ?
2010 NTSTATUS
cli_full_connection(struct cli_state
**output_cli
,
2011 const char *my_name
,
2012 const char *dest_host
,
2013 struct sockaddr_storage
*dest_ss
, int port
,
2014 const char *service
, const char *service_type
,
2015 const char *user
, const char *domain
,
2016 const char *password
, int flags
,
2021 struct cli_state
*cli
= NULL
;
2022 int pw_len
= password
? strlen(password
)+1 : 0;
2026 if (password
== NULL
) {
2030 nt_status
= cli_start_connection(&cli
, my_name
, dest_host
,
2031 dest_ss
, port
, signing_state
,
2034 if (!NT_STATUS_IS_OK(nt_status
)) {
2038 nt_status
= cli_session_setup(cli
, user
, password
, pw_len
, password
,
2040 if (!NT_STATUS_IS_OK(nt_status
)) {
2042 if (!(flags
& CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK
)) {
2043 DEBUG(1,("failed session setup with %s\n",
2044 nt_errstr(nt_status
)));
2049 nt_status
= cli_session_setup(cli
, "", "", 0, "", 0, domain
);
2050 if (!NT_STATUS_IS_OK(nt_status
)) {
2051 DEBUG(1,("anonymous failed session setup with %s\n",
2052 nt_errstr(nt_status
)));
2059 nt_status
= cli_tcon_andx(cli
, service
, service_type
, password
,
2061 if (!NT_STATUS_IS_OK(nt_status
)) {
2062 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status
)));
2064 if (NT_STATUS_IS_OK(nt_status
)) {
2065 nt_status
= NT_STATUS_UNSUCCESSFUL
;
2071 cli_init_creds(cli
, user
, domain
, password
);
2074 return NT_STATUS_OK
;
2077 /****************************************************************************
2078 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2079 ****************************************************************************/
2081 bool attempt_netbios_session_request(struct cli_state
**ppcli
, const char *srchost
, const char *desthost
,
2082 struct sockaddr_storage
*pdest_ss
)
2084 struct nmb_name calling
, called
;
2086 make_nmb_name(&calling
, srchost
, 0x0);
2089 * If the called name is an IP address
2090 * then use *SMBSERVER immediately.
2093 if(is_ipaddress(desthost
)) {
2094 make_nmb_name(&called
, STAR_SMBSERVER
, 0x20);
2096 make_nmb_name(&called
, desthost
, 0x20);
2099 if (!cli_session_request(*ppcli
, &calling
, &called
)) {
2101 struct nmb_name smbservername
;
2103 make_nmb_name(&smbservername
, STAR_SMBSERVER
, 0x20);
2106 * If the name wasn't *SMBSERVER then
2107 * try with *SMBSERVER if the first name fails.
2110 if (nmb_name_equal(&called
, &smbservername
)) {
2113 * The name used was *SMBSERVER, don't bother with another name.
2116 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2117 with error %s.\n", desthost
, cli_errstr(*ppcli
) ));
2122 cli_shutdown(*ppcli
);
2124 *ppcli
= cli_initialise();
2126 /* Out of memory... */
2130 status
= cli_connect(*ppcli
, desthost
, pdest_ss
);
2131 if (!NT_STATUS_IS_OK(status
) ||
2132 !cli_session_request(*ppcli
, &calling
, &smbservername
)) {
2133 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2134 name *SMBSERVER with error %s\n", desthost
, cli_errstr(*ppcli
) ));
2142 /****************************************************************************
2143 Send an old style tcon.
2144 ****************************************************************************/
2145 NTSTATUS
cli_raw_tcon(struct cli_state
*cli
,
2146 const char *service
, const char *pass
, const char *dev
,
2147 uint16
*max_xmit
, uint16
*tid
)
2151 if (!lp_client_plaintext_auth() && (*pass
)) {
2152 DEBUG(1, ("Server requested plaintext password but 'client "
2153 "plaintext auth' is disabled\n"));
2154 return NT_STATUS_ACCESS_DENIED
;
2157 memset(cli
->outbuf
,'\0',smb_size
);
2158 memset(cli
->inbuf
,'\0',smb_size
);
2160 cli_set_message(cli
->outbuf
, 0, 0, True
);
2161 SCVAL(cli
->outbuf
,smb_com
,SMBtcon
);
2162 cli_setup_packet(cli
);
2164 p
= smb_buf(cli
->outbuf
);
2165 *p
++ = 4; p
+= clistr_push(cli
, p
, service
, -1, STR_TERMINATE
| STR_NOALIGN
);
2166 *p
++ = 4; p
+= clistr_push(cli
, p
, pass
, -1, STR_TERMINATE
| STR_NOALIGN
);
2167 *p
++ = 4; p
+= clistr_push(cli
, p
, dev
, -1, STR_TERMINATE
| STR_NOALIGN
);
2169 cli_setup_bcc(cli
, p
);
2172 if (!cli_receive_smb(cli
)) {
2173 return NT_STATUS_UNEXPECTED_NETWORK_ERROR
;
2176 if (cli_is_error(cli
)) {
2177 return cli_nt_error(cli
);
2180 *max_xmit
= SVAL(cli
->inbuf
, smb_vwv0
);
2181 *tid
= SVAL(cli
->inbuf
, smb_vwv1
);
2183 return NT_STATUS_OK
;
2186 /* Return a cli_state pointing at the IPC$ share for the given server */
2188 struct cli_state
*get_ipc_connect(char *server
,
2189 struct sockaddr_storage
*server_ss
,
2190 const struct user_auth_info
*user_info
)
2192 struct cli_state
*cli
;
2194 uint32_t flags
= CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK
;
2196 if (user_info
->use_kerberos
) {
2197 flags
|= CLI_FULL_CONNECTION_USE_KERBEROS
;
2200 nt_status
= cli_full_connection(&cli
, NULL
, server
, server_ss
, 0, "IPC$", "IPC",
2201 user_info
->username
? user_info
->username
: "",
2203 user_info
->password
? user_info
->password
: "",
2207 if (NT_STATUS_IS_OK(nt_status
)) {
2209 } else if (is_ipaddress(server
)) {
2210 /* windows 9* needs a correct NMB name for connections */
2211 fstring remote_name
;
2213 if (name_status_find("*", 0, 0, server_ss
, remote_name
)) {
2214 cli
= get_ipc_connect(remote_name
, server_ss
, user_info
);
2223 * Given the IP address of a master browser on the network, return its
2224 * workgroup and connect to it.
2226 * This function is provided to allow additional processing beyond what
2227 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2228 * browsers and obtain each master browsers' list of domains (in case the
2229 * first master browser is recently on the network and has not yet
2230 * synchronized with other master browsers and therefore does not yet have the
2231 * entire network browse list)
2234 struct cli_state
*get_ipc_connect_master_ip(TALLOC_CTX
*ctx
,
2235 struct ip_service
*mb_ip
,
2236 const struct user_auth_info
*user_info
,
2237 char **pp_workgroup_out
)
2239 char addr
[INET6_ADDRSTRLEN
];
2241 struct cli_state
*cli
;
2242 struct sockaddr_storage server_ss
;
2244 *pp_workgroup_out
= NULL
;
2246 print_sockaddr(addr
, sizeof(addr
), &mb_ip
->ss
);
2247 DEBUG(99, ("Looking up name of master browser %s\n",
2251 * Do a name status query to find out the name of the master browser.
2252 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2253 * master browser will not respond to a wildcard query (or, at least,
2254 * an NT4 server acting as the domain master browser will not).
2256 * We might be able to use ONLY the query on MSBROWSE, but that's not
2257 * yet been tested with all Windows versions, so until it is, leave
2258 * the original wildcard query as the first choice and fall back to
2259 * MSBROWSE if the wildcard query fails.
2261 if (!name_status_find("*", 0, 0x1d, &mb_ip
->ss
, name
) &&
2262 !name_status_find(MSBROWSE
, 1, 0x1d, &mb_ip
->ss
, name
)) {
2264 DEBUG(99, ("Could not retrieve name status for %s\n",
2269 if (!find_master_ip(name
, &server_ss
)) {
2270 DEBUG(99, ("Could not find master ip for %s\n", name
));
2274 *pp_workgroup_out
= talloc_strdup(ctx
, name
);
2276 DEBUG(4, ("found master browser %s, %s\n", name
, addr
));
2278 print_sockaddr(addr
, sizeof(addr
), &server_ss
);
2279 cli
= get_ipc_connect(addr
, &server_ss
, user_info
);
2285 * Return the IP address and workgroup of a master browser on the network, and
2289 struct cli_state
*get_ipc_connect_master_ip_bcast(TALLOC_CTX
*ctx
,
2290 const struct user_auth_info
*user_info
,
2291 char **pp_workgroup_out
)
2293 struct ip_service
*ip_list
;
2294 struct cli_state
*cli
;
2297 *pp_workgroup_out
= NULL
;
2299 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2301 /* Go looking for workgroups by broadcasting on the local network */
2303 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE
, 1, &ip_list
,
2305 DEBUG(99, ("No master browsers responded\n"));
2309 for (i
= 0; i
< count
; i
++) {
2310 char addr
[INET6_ADDRSTRLEN
];
2311 print_sockaddr(addr
, sizeof(addr
), &ip_list
[i
].ss
);
2312 DEBUG(99, ("Found master browser %s\n", addr
));
2314 cli
= get_ipc_connect_master_ip(ctx
, &ip_list
[i
],
2315 user_info
, pp_workgroup_out
);