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", 5, NULL
);
192 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "Samba", 6, NULL
);
198 result
= cli_request_send(mem_ctx
, ev
, cli
, SMBsesssetupX
, 0,
199 13, vwv
, 0, talloc_get_size(bytes
), bytes
);
204 NTSTATUS
cli_session_setup_guest_recv(struct async_req
*req
)
206 struct cli_request
*cli_req
= talloc_get_type_abort(
207 req
->private_data
, struct cli_request
);
208 struct cli_state
*cli
= cli_req
->cli
;
216 if (async_req_is_nterror(req
, &status
)) {
220 status
= cli_pull_reply(req
, &wct
, &vwv
, &num_bytes
, &bytes
);
221 if (!NT_STATUS_IS_OK(status
)) {
227 cli
->vuid
= SVAL(cli_req
->inbuf
, smb_uid
);
229 p
+= clistr_pull(cli_req
->inbuf
, cli
->server_os
, (char *)p
,
230 sizeof(fstring
), bytes
+num_bytes
-p
, STR_TERMINATE
);
231 p
+= clistr_pull(cli_req
->inbuf
, cli
->server_type
, (char *)p
,
232 sizeof(fstring
), bytes
+num_bytes
-p
, STR_TERMINATE
);
233 p
+= clistr_pull(cli_req
->inbuf
, cli
->server_domain
, (char *)p
,
234 sizeof(fstring
), bytes
+num_bytes
-p
, STR_TERMINATE
);
236 if (strstr(cli
->server_type
, "Samba")) {
237 cli
->is_samba
= True
;
240 fstrcpy(cli
->user_name
, "");
245 static NTSTATUS
cli_session_setup_guest(struct cli_state
*cli
)
247 TALLOC_CTX
*frame
= talloc_stackframe();
248 struct event_context
*ev
;
249 struct async_req
*req
;
252 if (cli
->fd_event
!= NULL
) {
254 * Can't use sync call while an async call is in flight
256 status
= NT_STATUS_INVALID_PARAMETER
;
260 ev
= event_context_init(frame
);
262 status
= NT_STATUS_NO_MEMORY
;
266 req
= cli_session_setup_guest_send(frame
, ev
, cli
);
268 status
= NT_STATUS_NO_MEMORY
;
272 while (req
->state
< ASYNC_REQ_DONE
) {
276 status
= cli_session_setup_guest_recv(req
);
282 /****************************************************************************
283 Do a NT1 plaintext session setup.
284 ****************************************************************************/
286 static NTSTATUS
cli_session_setup_plaintext(struct cli_state
*cli
,
287 const char *user
, const char *pass
,
288 const char *workgroup
)
290 uint32 capabilities
= cli_session_setup_capabilities(cli
);
294 fstr_sprintf( lanman
, "Samba %s", samba_version_string());
296 memset(cli
->outbuf
, '\0', smb_size
);
297 cli_set_message(cli
->outbuf
,13,0,True
);
298 SCVAL(cli
->outbuf
,smb_com
,SMBsesssetupX
);
299 cli_setup_packet(cli
);
301 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
302 SSVAL(cli
->outbuf
,smb_vwv2
,CLI_BUFFER_SIZE
);
303 SSVAL(cli
->outbuf
,smb_vwv3
,2);
304 SSVAL(cli
->outbuf
,smb_vwv4
,cli
->pid
);
305 SIVAL(cli
->outbuf
,smb_vwv5
,cli
->sesskey
);
306 SSVAL(cli
->outbuf
,smb_vwv8
,0);
307 SIVAL(cli
->outbuf
,smb_vwv11
,capabilities
);
308 p
= smb_buf(cli
->outbuf
);
310 /* check wether to send the ASCII or UNICODE version of the password */
312 if ( (capabilities
& CAP_UNICODE
) == 0 ) {
313 p
+= clistr_push(cli
, p
, pass
, -1, STR_TERMINATE
); /* password */
314 SSVAL(cli
->outbuf
,smb_vwv7
,PTR_DIFF(p
, smb_buf(cli
->outbuf
)));
317 /* For ucs2 passwords clistr_push calls ucs2_align, which causes
318 * the space taken by the unicode password to be one byte too
319 * long (as we're on an odd byte boundary here). Reduce the
320 * count by 1 to cope with this. Fixes smbclient against NetApp
321 * servers which can't cope. Fix from
322 * bryan.kolodziej@allenlund.com in bug #3840.
324 p
+= clistr_push(cli
, p
, pass
, -1, STR_UNICODE
|STR_TERMINATE
); /* unicode password */
325 SSVAL(cli
->outbuf
,smb_vwv8
,PTR_DIFF(p
, smb_buf(cli
->outbuf
))-1);
328 p
+= clistr_push(cli
, p
, user
, -1, STR_TERMINATE
); /* username */
329 p
+= clistr_push(cli
, p
, workgroup
, -1, STR_TERMINATE
); /* workgroup */
330 p
+= clistr_push(cli
, p
, "Unix", -1, STR_TERMINATE
);
331 p
+= clistr_push(cli
, p
, lanman
, -1, STR_TERMINATE
);
332 cli_setup_bcc(cli
, p
);
334 if (!cli_send_smb(cli
) || !cli_receive_smb(cli
)) {
335 return cli_nt_error(cli
);
338 show_msg(cli
->inbuf
);
340 if (cli_is_error(cli
)) {
341 return cli_nt_error(cli
);
344 cli
->vuid
= SVAL(cli
->inbuf
,smb_uid
);
345 p
= smb_buf(cli
->inbuf
);
346 p
+= clistr_pull(cli
->inbuf
, cli
->server_os
, p
, sizeof(fstring
),
348 p
+= clistr_pull(cli
->inbuf
, cli
->server_type
, p
, sizeof(fstring
),
350 p
+= clistr_pull(cli
->inbuf
, cli
->server_domain
, p
, sizeof(fstring
),
352 fstrcpy(cli
->user_name
, user
);
354 if (strstr(cli
->server_type
, "Samba")) {
355 cli
->is_samba
= True
;
361 /****************************************************************************
362 do a NT1 NTLM/LM encrypted session setup - for when extended security
364 @param cli client state to create do session setup on
366 @param pass *either* cleartext password (passlen !=24) or LM response.
367 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
368 @param workgroup The user's domain.
369 ****************************************************************************/
371 static NTSTATUS
cli_session_setup_nt1(struct cli_state
*cli
, const char *user
,
372 const char *pass
, size_t passlen
,
373 const char *ntpass
, size_t ntpasslen
,
374 const char *workgroup
)
376 uint32 capabilities
= cli_session_setup_capabilities(cli
);
377 DATA_BLOB lm_response
= data_blob_null
;
378 DATA_BLOB nt_response
= data_blob_null
;
379 DATA_BLOB session_key
= data_blob_null
;
384 /* do nothing - guest login */
385 } else if (passlen
!= 24) {
386 if (lp_client_ntlmv2_auth()) {
387 DATA_BLOB server_chal
;
388 DATA_BLOB names_blob
;
389 server_chal
= data_blob(cli
->secblob
.data
, MIN(cli
->secblob
.length
, 8));
391 /* note that the 'workgroup' here is a best guess - we don't know
392 the server's domain at this point. The 'server name' is also
395 names_blob
= NTLMv2_generate_names_blob(cli
->called
.name
, workgroup
);
397 if (!SMBNTLMv2encrypt(user
, workgroup
, pass
, &server_chal
,
399 &lm_response
, &nt_response
, &session_key
)) {
400 data_blob_free(&names_blob
);
401 data_blob_free(&server_chal
);
402 return NT_STATUS_ACCESS_DENIED
;
404 data_blob_free(&names_blob
);
405 data_blob_free(&server_chal
);
409 E_md4hash(pass
, nt_hash
);
412 nt_response
= data_blob_null
;
414 nt_response
= data_blob(NULL
, 24);
415 SMBNTencrypt(pass
,cli
->secblob
.data
,nt_response
.data
);
417 /* non encrypted password supplied. Ignore ntpass. */
418 if (lp_client_lanman_auth()) {
419 lm_response
= data_blob(NULL
, 24);
420 if (!SMBencrypt(pass
,cli
->secblob
.data
, lm_response
.data
)) {
421 /* Oops, the LM response is invalid, just put
422 the NT response there instead */
423 data_blob_free(&lm_response
);
424 lm_response
= data_blob(nt_response
.data
, nt_response
.length
);
427 /* LM disabled, place NT# in LM field instead */
428 lm_response
= data_blob(nt_response
.data
, nt_response
.length
);
431 session_key
= data_blob(NULL
, 16);
433 E_deshash(pass
, session_key
.data
);
434 memset(&session_key
.data
[8], '\0', 8);
436 SMBsesskeygen_ntv1(nt_hash
, NULL
, session_key
.data
);
440 cli_simple_set_signing(cli
, session_key
, lm_response
);
442 cli_simple_set_signing(cli
, session_key
, nt_response
);
445 /* pre-encrypted password supplied. Only used for
446 security=server, can't do
447 signing because we don't have original key */
449 lm_response
= data_blob(pass
, passlen
);
450 nt_response
= data_blob(ntpass
, ntpasslen
);
453 /* send a session setup command */
454 memset(cli
->outbuf
,'\0',smb_size
);
456 cli_set_message(cli
->outbuf
,13,0,True
);
457 SCVAL(cli
->outbuf
,smb_com
,SMBsesssetupX
);
458 cli_setup_packet(cli
);
460 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
461 SSVAL(cli
->outbuf
,smb_vwv2
,CLI_BUFFER_SIZE
);
462 SSVAL(cli
->outbuf
,smb_vwv3
,2);
463 SSVAL(cli
->outbuf
,smb_vwv4
,cli
->pid
);
464 SIVAL(cli
->outbuf
,smb_vwv5
,cli
->sesskey
);
465 SSVAL(cli
->outbuf
,smb_vwv7
,lm_response
.length
);
466 SSVAL(cli
->outbuf
,smb_vwv8
,nt_response
.length
);
467 SIVAL(cli
->outbuf
,smb_vwv11
,capabilities
);
468 p
= smb_buf(cli
->outbuf
);
469 if (lm_response
.length
) {
470 memcpy(p
,lm_response
.data
, lm_response
.length
); p
+= lm_response
.length
;
472 if (nt_response
.length
) {
473 memcpy(p
,nt_response
.data
, nt_response
.length
); p
+= nt_response
.length
;
475 p
+= clistr_push(cli
, p
, user
, -1, STR_TERMINATE
);
477 /* Upper case here might help some NTLMv2 implementations */
478 p
+= clistr_push(cli
, p
, workgroup
, -1, STR_TERMINATE
|STR_UPPER
);
479 p
+= clistr_push(cli
, p
, "Unix", -1, STR_TERMINATE
);
480 p
+= clistr_push(cli
, p
, "Samba", -1, STR_TERMINATE
);
481 cli_setup_bcc(cli
, p
);
483 if (!cli_send_smb(cli
) || !cli_receive_smb(cli
)) {
484 result
= cli_nt_error(cli
);
488 /* show_msg(cli->inbuf); */
490 if (cli_is_error(cli
)) {
491 result
= cli_nt_error(cli
);
495 /* use the returned vuid from now on */
496 cli
->vuid
= SVAL(cli
->inbuf
,smb_uid
);
498 p
= smb_buf(cli
->inbuf
);
499 p
+= clistr_pull(cli
->inbuf
, cli
->server_os
, p
, sizeof(fstring
),
501 p
+= clistr_pull(cli
->inbuf
, cli
->server_type
, p
, sizeof(fstring
),
503 p
+= clistr_pull(cli
->inbuf
, cli
->server_domain
, p
, sizeof(fstring
),
506 if (strstr(cli
->server_type
, "Samba")) {
507 cli
->is_samba
= True
;
510 fstrcpy(cli
->user_name
, user
);
512 if (session_key
.data
) {
513 /* Have plaintext orginal */
514 cli_set_session_key(cli
, session_key
);
517 result
= NT_STATUS_OK
;
519 data_blob_free(&lm_response
);
520 data_blob_free(&nt_response
);
521 data_blob_free(&session_key
);
525 /****************************************************************************
526 Send a extended security session setup blob
527 ****************************************************************************/
529 static bool cli_session_setup_blob_send(struct cli_state
*cli
, DATA_BLOB blob
)
531 uint32 capabilities
= cli_session_setup_capabilities(cli
);
534 capabilities
|= CAP_EXTENDED_SECURITY
;
536 /* send a session setup command */
537 memset(cli
->outbuf
,'\0',smb_size
);
539 cli_set_message(cli
->outbuf
,12,0,True
);
540 SCVAL(cli
->outbuf
,smb_com
,SMBsesssetupX
);
542 cli_setup_packet(cli
);
544 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
545 SSVAL(cli
->outbuf
,smb_vwv2
,CLI_BUFFER_SIZE
);
546 SSVAL(cli
->outbuf
,smb_vwv3
,2);
547 SSVAL(cli
->outbuf
,smb_vwv4
,1);
548 SIVAL(cli
->outbuf
,smb_vwv5
,0);
549 SSVAL(cli
->outbuf
,smb_vwv7
,blob
.length
);
550 SIVAL(cli
->outbuf
,smb_vwv10
,capabilities
);
551 p
= smb_buf(cli
->outbuf
);
552 memcpy(p
, blob
.data
, blob
.length
);
554 p
+= clistr_push(cli
, p
, "Unix", -1, STR_TERMINATE
);
555 p
+= clistr_push(cli
, p
, "Samba", -1, STR_TERMINATE
);
556 cli_setup_bcc(cli
, p
);
557 return cli_send_smb(cli
);
560 /****************************************************************************
561 Send a extended security session setup blob, returning a reply blob.
562 ****************************************************************************/
564 static DATA_BLOB
cli_session_setup_blob_receive(struct cli_state
*cli
)
566 DATA_BLOB blob2
= data_blob_null
;
570 if (!cli_receive_smb(cli
))
573 show_msg(cli
->inbuf
);
575 if (cli_is_error(cli
) && !NT_STATUS_EQUAL(cli_nt_error(cli
),
576 NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
580 /* use the returned vuid from now on */
581 cli
->vuid
= SVAL(cli
->inbuf
,smb_uid
);
583 p
= smb_buf(cli
->inbuf
);
585 blob2
= data_blob(p
, SVAL(cli
->inbuf
, smb_vwv3
));
588 p
+= clistr_pull(cli
->inbuf
, cli
->server_os
, p
, sizeof(fstring
),
591 /* w2k with kerberos doesn't properly null terminate this field */
592 len
= smb_bufrem(cli
->inbuf
, p
);
593 p
+= clistr_pull(cli
->inbuf
, cli
->server_type
, p
, sizeof(fstring
),
600 /****************************************************************************
601 Send a extended security session setup blob, returning a reply blob.
602 ****************************************************************************/
604 /* The following is calculated from :
606 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
607 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
611 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
613 static bool cli_session_setup_blob(struct cli_state
*cli
, DATA_BLOB blob
)
615 int32 remaining
= blob
.length
;
617 DATA_BLOB send_blob
= data_blob_null
;
618 int32 max_blob_size
= 0;
619 DATA_BLOB receive_blob
= data_blob_null
;
621 if (cli
->max_xmit
< BASE_SESSSETUP_BLOB_PACKET_SIZE
+ 1) {
622 DEBUG(0,("cli_session_setup_blob: cli->max_xmit too small "
623 "(was %u, need minimum %u)\n",
624 (unsigned int)cli
->max_xmit
,
625 BASE_SESSSETUP_BLOB_PACKET_SIZE
));
626 cli_set_nt_error(cli
, NT_STATUS_INVALID_PARAMETER
);
630 max_blob_size
= cli
->max_xmit
- BASE_SESSSETUP_BLOB_PACKET_SIZE
;
632 while ( remaining
> 0) {
633 if (remaining
>= max_blob_size
) {
634 send_blob
.length
= max_blob_size
;
635 remaining
-= max_blob_size
;
637 send_blob
.length
= remaining
;
641 send_blob
.data
= &blob
.data
[cur
];
642 cur
+= send_blob
.length
;
644 DEBUG(10, ("cli_session_setup_blob: Remaining (%u) sending (%u) current (%u)\n",
645 (unsigned int)remaining
,
646 (unsigned int)send_blob
.length
,
647 (unsigned int)cur
));
649 if (!cli_session_setup_blob_send(cli
, send_blob
)) {
650 DEBUG(0, ("cli_session_setup_blob: send failed\n"));
654 receive_blob
= cli_session_setup_blob_receive(cli
);
655 data_blob_free(&receive_blob
);
657 if (cli_is_error(cli
) &&
658 !NT_STATUS_EQUAL( cli_get_nt_error(cli
),
659 NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
660 DEBUG(0, ("cli_session_setup_blob: receive failed "
661 "(%s)\n", nt_errstr(cli_get_nt_error(cli
))));
670 /****************************************************************************
671 Use in-memory credentials cache
672 ****************************************************************************/
674 static void use_in_memory_ccache(void) {
675 setenv(KRB5_ENV_CCNAME
, "MEMORY:cliconnect", 1);
678 /****************************************************************************
679 Do a spnego/kerberos encrypted session setup.
680 ****************************************************************************/
682 static ADS_STATUS
cli_session_setup_kerberos(struct cli_state
*cli
, const char *principal
, const char *workgroup
)
684 DATA_BLOB negTokenTarg
;
685 DATA_BLOB session_key_krb5
;
689 cli_temp_set_signing(cli
);
691 DEBUG(2,("Doing kerberos session setup\n"));
693 /* generate the encapsulated kerberos5 ticket */
694 rc
= spnego_gen_negTokenTarg(principal
, 0, &negTokenTarg
, &session_key_krb5
, 0, NULL
);
697 DEBUG(1, ("cli_session_setup_kerberos: spnego_gen_negTokenTarg failed: %s\n",
699 return ADS_ERROR_KRB5(rc
);
703 file_save("negTokenTarg.dat", negTokenTarg
.data
, negTokenTarg
.length
);
706 if (!cli_session_setup_blob(cli
, negTokenTarg
)) {
707 nt_status
= cli_nt_error(cli
);
711 if (cli_is_error(cli
)) {
712 nt_status
= cli_nt_error(cli
);
713 if (NT_STATUS_IS_OK(nt_status
)) {
714 nt_status
= NT_STATUS_UNSUCCESSFUL
;
719 cli_set_session_key(cli
, session_key_krb5
);
721 if (cli_simple_set_signing(
722 cli
, session_key_krb5
, data_blob_null
)) {
724 /* 'resign' the last message, so we get the right sequence numbers
725 for checking the first reply from the server */
726 cli_calculate_sign_mac(cli
, cli
->outbuf
);
728 if (!cli_check_sign_mac(cli
, cli
->inbuf
)) {
729 nt_status
= NT_STATUS_ACCESS_DENIED
;
734 data_blob_free(&negTokenTarg
);
735 data_blob_free(&session_key_krb5
);
737 return ADS_ERROR_NT(NT_STATUS_OK
);
740 data_blob_free(&negTokenTarg
);
741 data_blob_free(&session_key_krb5
);
743 return ADS_ERROR_NT(nt_status
);
745 #endif /* HAVE_KRB5 */
748 /****************************************************************************
749 Do a spnego/NTLMSSP encrypted session setup.
750 ****************************************************************************/
752 static NTSTATUS
cli_session_setup_ntlmssp(struct cli_state
*cli
, const char *user
,
753 const char *pass
, const char *domain
)
755 struct ntlmssp_state
*ntlmssp_state
;
759 DATA_BLOB blob
= data_blob_null
;
760 DATA_BLOB blob_in
= data_blob_null
;
761 DATA_BLOB blob_out
= data_blob_null
;
763 cli_temp_set_signing(cli
);
765 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_client_start(&ntlmssp_state
))) {
768 ntlmssp_want_feature(ntlmssp_state
, NTLMSSP_FEATURE_SESSION_KEY
);
770 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_username(ntlmssp_state
, user
))) {
773 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_domain(ntlmssp_state
, domain
))) {
776 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_password(ntlmssp_state
, pass
))) {
781 nt_status
= ntlmssp_update(ntlmssp_state
,
783 data_blob_free(&blob_in
);
784 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) || NT_STATUS_IS_OK(nt_status
)) {
786 /* and wrap it in a SPNEGO wrapper */
787 msg1
= gen_negTokenInit(OID_NTLMSSP
, blob_out
);
789 /* wrap it in SPNEGO */
790 msg1
= spnego_gen_auth(blob_out
);
793 /* now send that blob on its way */
794 if (!cli_session_setup_blob_send(cli
, msg1
)) {
795 DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
796 nt_status
= NT_STATUS_UNSUCCESSFUL
;
798 blob
= cli_session_setup_blob_receive(cli
);
800 nt_status
= cli_nt_error(cli
);
801 if (cli_is_error(cli
) && NT_STATUS_IS_OK(nt_status
)) {
802 if (cli
->smb_rw_error
== SMB_READ_BAD_SIG
) {
803 nt_status
= NT_STATUS_ACCESS_DENIED
;
805 nt_status
= NT_STATUS_UNSUCCESSFUL
;
809 data_blob_free(&msg1
);
813 if (NT_STATUS_IS_OK(nt_status
)) {
814 nt_status
= NT_STATUS_UNSUCCESSFUL
;
816 } else if ((turn
== 1) &&
817 NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
818 DATA_BLOB tmp_blob
= data_blob_null
;
819 /* the server might give us back two challenges */
820 if (!spnego_parse_challenge(blob
, &blob_in
,
822 DEBUG(3,("Failed to parse challenges\n"));
823 nt_status
= NT_STATUS_INVALID_PARAMETER
;
825 data_blob_free(&tmp_blob
);
827 if (!spnego_parse_auth_response(blob
, nt_status
, OID_NTLMSSP
,
829 DEBUG(3,("Failed to parse auth response\n"));
830 if (NT_STATUS_IS_OK(nt_status
)
831 || NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
))
832 nt_status
= NT_STATUS_INVALID_PARAMETER
;
835 data_blob_free(&blob
);
836 data_blob_free(&blob_out
);
838 } while (NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
));
840 data_blob_free(&blob_in
);
842 if (NT_STATUS_IS_OK(nt_status
)) {
844 fstrcpy(cli
->server_domain
, ntlmssp_state
->server_domain
);
845 cli_set_session_key(cli
, ntlmssp_state
->session_key
);
847 if (cli_simple_set_signing(
848 cli
, ntlmssp_state
->session_key
, data_blob_null
)) {
850 /* 'resign' the last message, so we get the right sequence numbers
851 for checking the first reply from the server */
852 cli_calculate_sign_mac(cli
, cli
->outbuf
);
854 if (!cli_check_sign_mac(cli
, cli
->inbuf
)) {
855 nt_status
= NT_STATUS_ACCESS_DENIED
;
860 /* we have a reference conter on ntlmssp_state, if we are signing
861 then the state will be kept by the signing engine */
863 ntlmssp_end(&ntlmssp_state
);
865 if (!NT_STATUS_IS_OK(nt_status
)) {
871 /****************************************************************************
872 Do a spnego encrypted session setup.
874 user_domain: The shortname of the domain the user/machine is a member of.
875 dest_realm: The realm we're connecting to, if NULL we use our default realm.
876 ****************************************************************************/
878 ADS_STATUS
cli_session_setup_spnego(struct cli_state
*cli
, const char *user
,
879 const char *pass
, const char *user_domain
,
880 const char * dest_realm
)
882 char *principal
= NULL
;
883 char *OIDs
[ASN1_MAX_OIDS
];
886 const char *p
= NULL
;
887 char *account
= NULL
;
889 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli
->secblob
.length
));
891 /* the server might not even do spnego */
892 if (cli
->secblob
.length
<= 16) {
893 DEBUG(3,("server didn't supply a full spnego negprot\n"));
898 file_save("negprot.dat", cli
->secblob
.data
, cli
->secblob
.length
);
901 /* there is 16 bytes of GUID before the real spnego packet starts */
902 blob
= data_blob(cli
->secblob
.data
+16, cli
->secblob
.length
-16);
904 /* The server sent us the first part of the SPNEGO exchange in the
905 * negprot reply. It is WRONG to depend on the principal sent in the
906 * negprot reply, but right now we do it. If we don't receive one,
907 * we try to best guess, then fall back to NTLM. */
908 if (!spnego_parse_negTokenInit(blob
, OIDs
, &principal
)) {
909 data_blob_free(&blob
);
910 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
912 data_blob_free(&blob
);
914 /* make sure the server understands kerberos */
915 for (i
=0;OIDs
[i
];i
++) {
916 DEBUG(3,("got OID=%s\n", OIDs
[i
]));
917 if (strcmp(OIDs
[i
], OID_KERBEROS5_OLD
) == 0 ||
918 strcmp(OIDs
[i
], OID_KERBEROS5
) == 0) {
919 cli
->got_kerberos_mechanism
= True
;
921 talloc_free(OIDs
[i
]);
924 DEBUG(3,("got principal=%s\n", principal
? principal
: "<null>"));
926 fstrcpy(cli
->user_name
, user
);
929 /* If password is set we reauthenticate to kerberos server
930 * and do not store results */
932 if (cli
->got_kerberos_mechanism
&& cli
->use_kerberos
) {
938 use_in_memory_ccache();
939 ret
= kerberos_kinit_password(user
, pass
, 0 /* no time correction for now */, NULL
);
942 TALLOC_FREE(principal
);
943 DEBUG(0, ("Kinit failed: %s\n", error_message(ret
)));
944 if (cli
->fallback_after_kerberos
)
946 return ADS_ERROR_KRB5(ret
);
950 /* If we get a bad principal, try to guess it if
951 we have a valid host NetBIOS name.
953 if (strequal(principal
, ADS_IGNORE_PRINCIPAL
)) {
954 TALLOC_FREE(principal
);
957 if (principal
== NULL
&&
958 !is_ipaddress(cli
->desthost
) &&
959 !strequal(STAR_SMBSERVER
,
962 char *machine
= NULL
;
964 DEBUG(3,("cli_session_setup_spnego: got a "
965 "bad server principal, trying to guess ...\n"));
967 host
= strchr_m(cli
->desthost
, '.');
969 machine
= SMB_STRNDUP(cli
->desthost
,
970 host
- cli
->desthost
);
972 machine
= SMB_STRDUP(cli
->desthost
);
974 if (machine
== NULL
) {
975 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
979 realm
= SMB_STRDUP(dest_realm
);
982 realm
= kerberos_get_default_realm_from_ccache();
984 if (realm
&& *realm
) {
985 principal
= talloc_asprintf(NULL
, "%s$@%s",
990 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
992 DEBUG(3,("cli_session_setup_spnego: guessed "
993 "server principal=%s\n",
994 principal
? principal
: "<null>"));
1001 rc
= cli_session_setup_kerberos(cli
, principal
,
1003 if (ADS_ERR_OK(rc
) || !cli
->fallback_after_kerberos
) {
1004 TALLOC_FREE(principal
);
1011 TALLOC_FREE(principal
);
1015 account
= talloc_strdup(talloc_tos(), user
);
1017 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
1020 /* when falling back to ntlmssp while authenticating with a machine
1021 * account strip off the realm - gd */
1023 if ((p
= strchr_m(user
, '@')) != NULL
) {
1024 account
[PTR_DIFF(p
,user
)] = '\0';
1027 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli
, account
, pass
, user_domain
));
1030 /****************************************************************************
1031 Send a session setup. The username and workgroup is in UNIX character
1032 format and must be converted to DOS codepage format before sending. If the
1033 password is in plaintext, the same should be done.
1034 ****************************************************************************/
1036 NTSTATUS
cli_session_setup(struct cli_state
*cli
,
1038 const char *pass
, int passlen
,
1039 const char *ntpass
, int ntpasslen
,
1040 const char *workgroup
)
1046 fstrcpy(user2
, user
);
1055 /* allow for workgroups as part of the username */
1056 if ((p
=strchr_m(user2
,'\\')) || (p
=strchr_m(user2
,'/')) ||
1057 (p
=strchr_m(user2
,*lp_winbind_separator()))) {
1063 if (cli
->protocol
< PROTOCOL_LANMAN1
) {
1064 return NT_STATUS_OK
;
1067 /* now work out what sort of session setup we are going to
1068 do. I have split this into separate functions to make the
1069 flow a bit easier to understand (tridge) */
1071 /* if its an older server then we have to use the older request format */
1073 if (cli
->protocol
< PROTOCOL_NT1
) {
1074 if (!lp_client_lanman_auth() && passlen
!= 24 && (*pass
)) {
1075 DEBUG(1, ("Server requested LM password but 'client lanman auth'"
1077 return NT_STATUS_ACCESS_DENIED
;
1080 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) == 0 &&
1081 !lp_client_plaintext_auth() && (*pass
)) {
1082 DEBUG(1, ("Server requested plaintext password but "
1083 "'client plaintext auth' is disabled\n"));
1084 return NT_STATUS_ACCESS_DENIED
;
1087 return cli_session_setup_lanman2(cli
, user
, pass
, passlen
,
1091 /* if no user is supplied then we have to do an anonymous connection.
1092 passwords are ignored */
1094 if (!user
|| !*user
)
1095 return cli_session_setup_guest(cli
);
1097 /* if the server is share level then send a plaintext null
1098 password at this point. The password is sent in the tree
1101 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
) == 0)
1102 return cli_session_setup_plaintext(cli
, user
, "", workgroup
);
1104 /* if the server doesn't support encryption then we have to use
1105 plaintext. The second password is ignored */
1107 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) == 0) {
1108 if (!lp_client_plaintext_auth() && (*pass
)) {
1109 DEBUG(1, ("Server requested plaintext password but "
1110 "'client plaintext auth' is disabled\n"));
1111 return NT_STATUS_ACCESS_DENIED
;
1113 return cli_session_setup_plaintext(cli
, user
, pass
, workgroup
);
1116 /* if the server supports extended security then use SPNEGO */
1118 if (cli
->capabilities
& CAP_EXTENDED_SECURITY
) {
1119 ADS_STATUS status
= cli_session_setup_spnego(cli
, user
, pass
,
1121 if (!ADS_ERR_OK(status
)) {
1122 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status
)));
1123 return ads_ntstatus(status
);
1128 /* otherwise do a NT1 style session setup */
1129 status
= cli_session_setup_nt1(cli
, user
, pass
, passlen
,
1130 ntpass
, ntpasslen
, workgroup
);
1131 if (!NT_STATUS_IS_OK(status
)) {
1132 DEBUG(3,("cli_session_setup: NT1 session setup "
1133 "failed: %s\n", nt_errstr(status
)));
1138 if (strstr(cli
->server_type
, "Samba")) {
1139 cli
->is_samba
= True
;
1142 return NT_STATUS_OK
;
1145 /****************************************************************************
1147 *****************************************************************************/
1149 bool cli_ulogoff(struct cli_state
*cli
)
1151 memset(cli
->outbuf
,'\0',smb_size
);
1152 cli_set_message(cli
->outbuf
,2,0,True
);
1153 SCVAL(cli
->outbuf
,smb_com
,SMBulogoffX
);
1154 cli_setup_packet(cli
);
1155 SSVAL(cli
->outbuf
,smb_vwv0
,0xFF);
1156 SSVAL(cli
->outbuf
,smb_vwv2
,0); /* no additional info */
1159 if (!cli_receive_smb(cli
))
1162 if (cli_is_error(cli
)) {
1170 /****************************************************************************
1172 ****************************************************************************/
1174 struct async_req
*cli_tcon_andx_send(TALLOC_CTX
*mem_ctx
,
1175 struct event_context
*ev
,
1176 struct cli_state
*cli
,
1177 const char *share
, const char *dev
,
1178 const char *pass
, int passlen
)
1182 struct async_req
*result
;
1186 fstrcpy(cli
->share
, share
);
1188 /* in user level security don't send a password now */
1189 if (cli
->sec_mode
& NEGOTIATE_SECURITY_USER_LEVEL
) {
1192 } else if (pass
== NULL
) {
1193 DEBUG(1, ("Server not using user level security and no "
1194 "password supplied.\n"));
1198 if ((cli
->sec_mode
& NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
) &&
1199 *pass
&& passlen
!= 24) {
1200 if (!lp_client_lanman_auth()) {
1201 DEBUG(1, ("Server requested LANMAN password "
1202 "(share-level security) but "
1203 "'client lanman auth' is disabled\n"));
1208 * Non-encrypted passwords - convert to DOS codepage before
1212 SMBencrypt(pass
, cli
->secblob
.data
, (uchar
*)pword
);
1214 if((cli
->sec_mode
& (NEGOTIATE_SECURITY_USER_LEVEL
1215 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
))
1217 if (!lp_client_plaintext_auth() && (*pass
)) {
1218 DEBUG(1, ("Server requested plaintext "
1219 "password but 'client plaintext "
1220 "auth' is disabled\n"));
1225 * Non-encrypted passwords - convert to DOS codepage
1228 passlen
= clistr_push(cli
, pword
, pass
, sizeof(pword
),
1230 if (passlen
== -1) {
1231 DEBUG(1, ("clistr_push(pword) failed\n"));
1236 memcpy(pword
, pass
, passlen
);
1241 SCVAL(vwv
+0, 0, 0xFF);
1244 SSVAL(vwv
+2, 0, TCONX_FLAG_EXTENDED_RESPONSE
);
1245 SSVAL(vwv
+3, 0, passlen
);
1248 bytes
= (uint8_t *)talloc_memdup(talloc_tos(), pword
, passlen
);
1250 bytes
= talloc_array(talloc_tos(), uint8_t, 0);
1256 tmp
= talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1257 cli
->desthost
, share
);
1262 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), tmp
, strlen(tmp
)+1,
1267 * Add the devicetype
1269 tmp
= talloc_strdup_upper(talloc_tos(), dev
);
1274 bytes
= smb_bytes_push_str(bytes
, false, tmp
, strlen(tmp
)+1, NULL
);
1277 if (bytes
== NULL
) {
1281 result
= cli_request_send(mem_ctx
, ev
, cli
, SMBtconX
, 0,
1282 4, vwv
, 0, talloc_get_size(bytes
), bytes
);
1287 result
= async_req_new(mem_ctx
);
1288 if (async_post_ntstatus(result
, ev
, NT_STATUS_ACCESS_DENIED
)) {
1291 TALLOC_FREE(result
);
1295 NTSTATUS
cli_tcon_andx_recv(struct async_req
*req
)
1297 struct cli_request
*cli_req
= talloc_get_type_abort(
1298 req
->private_data
, struct cli_request
);
1299 struct cli_state
*cli
= cli_req
->cli
;
1306 if (async_req_is_nterror(req
, &status
)) {
1310 status
= cli_pull_reply(req
, &wct
, &vwv
, &num_bytes
, &bytes
);
1311 if (!NT_STATUS_IS_OK(status
)) {
1315 clistr_pull(cli_req
->inbuf
, cli
->dev
, bytes
, sizeof(fstring
),
1316 num_bytes
, STR_TERMINATE
|STR_ASCII
);
1318 if ((cli
->protocol
>= PROTOCOL_NT1
) && (num_bytes
== 3)) {
1319 /* almost certainly win95 - enable bug fixes */
1324 * Make sure that we have the optional support 16-bit field. WCT > 2.
1325 * Avoids issues when connecting to Win9x boxes sharing files
1328 cli
->dfsroot
= false;
1330 if ((wct
> 2) && (cli
->protocol
>= PROTOCOL_LANMAN2
)) {
1331 cli
->dfsroot
= ((SVAL(vwv
+2, 0) & SMB_SHARE_IN_DFS
) != 0);
1334 cli
->cnum
= SVAL(cli_req
->inbuf
,smb_tid
);
1335 return NT_STATUS_OK
;
1338 NTSTATUS
cli_tcon_andx(struct cli_state
*cli
, const char *share
,
1339 const char *dev
, const char *pass
, int passlen
)
1341 TALLOC_CTX
*frame
= talloc_stackframe();
1342 struct event_context
*ev
;
1343 struct async_req
*req
;
1346 if (cli
->fd_event
!= NULL
) {
1348 * Can't use sync call while an async call is in flight
1350 status
= NT_STATUS_INVALID_PARAMETER
;
1354 ev
= event_context_init(frame
);
1356 status
= NT_STATUS_NO_MEMORY
;
1360 req
= cli_tcon_andx_send(frame
, ev
, cli
, share
, dev
, pass
, passlen
);
1362 status
= NT_STATUS_NO_MEMORY
;
1366 while (req
->state
< ASYNC_REQ_DONE
) {
1367 event_loop_once(ev
);
1370 status
= cli_tcon_andx_recv(req
);
1376 /****************************************************************************
1377 Send a tree disconnect.
1378 ****************************************************************************/
1380 bool cli_tdis(struct cli_state
*cli
)
1382 memset(cli
->outbuf
,'\0',smb_size
);
1383 cli_set_message(cli
->outbuf
,0,0,True
);
1384 SCVAL(cli
->outbuf
,smb_com
,SMBtdis
);
1385 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
1386 cli_setup_packet(cli
);
1389 if (!cli_receive_smb(cli
))
1392 if (cli_is_error(cli
)) {
1400 /****************************************************************************
1401 Send a negprot command.
1402 ****************************************************************************/
1404 void cli_negprot_sendsync(struct cli_state
*cli
)
1409 if (cli
->protocol
< PROTOCOL_NT1
)
1410 cli
->use_spnego
= False
;
1412 memset(cli
->outbuf
,'\0',smb_size
);
1414 /* setup the protocol strings */
1415 cli_set_message(cli
->outbuf
,0,0,True
);
1417 p
= smb_buf(cli
->outbuf
);
1418 for (numprots
=0; numprots
< ARRAY_SIZE(prots
); numprots
++) {
1419 if (prots
[numprots
].prot
> cli
->protocol
) {
1423 p
+= clistr_push(cli
, p
, prots
[numprots
].name
, -1, STR_TERMINATE
);
1426 SCVAL(cli
->outbuf
,smb_com
,SMBnegprot
);
1427 cli_setup_bcc(cli
, p
);
1428 cli_setup_packet(cli
);
1430 SCVAL(smb_buf(cli
->outbuf
),0,2);
1435 /****************************************************************************
1436 Send a negprot command.
1437 ****************************************************************************/
1439 struct async_req
*cli_negprot_send(TALLOC_CTX
*mem_ctx
,
1440 struct event_context
*ev
,
1441 struct cli_state
*cli
)
1443 struct async_req
*result
;
1444 uint8_t *bytes
= NULL
;
1447 if (cli
->protocol
< PROTOCOL_NT1
)
1448 cli
->use_spnego
= False
;
1450 /* setup the protocol strings */
1451 for (numprots
=0; numprots
< ARRAY_SIZE(prots
); numprots
++) {
1453 if (prots
[numprots
].prot
> cli
->protocol
) {
1456 bytes
= (uint8_t *)talloc_append_blob(
1457 talloc_tos(), bytes
, data_blob_const(&c
, sizeof(c
)));
1458 if (bytes
== NULL
) {
1461 bytes
= smb_bytes_push_str(bytes
, false,
1462 prots
[numprots
].name
,
1463 strlen(prots
[numprots
].name
)+1,
1465 if (bytes
== NULL
) {
1470 result
= cli_request_send(mem_ctx
, ev
, cli
, SMBnegprot
, 0, 0, NULL
, 0,
1471 talloc_get_size(bytes
), bytes
);
1476 NTSTATUS
cli_negprot_recv(struct async_req
*req
)
1478 struct cli_request
*cli_req
= talloc_get_type_abort(
1479 req
->private_data
, struct cli_request
);
1480 struct cli_state
*cli
= cli_req
->cli
;
1488 if (async_req_is_nterror(req
, &status
)) {
1492 status
= cli_pull_reply(req
, &wct
, &vwv
, &num_bytes
, &bytes
);
1493 if (!NT_STATUS_IS_OK(status
)) {
1497 protnum
= SVAL(vwv
, 0);
1499 if ((protnum
>= ARRAY_SIZE(prots
))
1500 || (prots
[protnum
].prot
> cli_req
->cli
->protocol
)) {
1501 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
1504 cli
->protocol
= prots
[protnum
].prot
;
1506 if ((cli
->protocol
< PROTOCOL_NT1
) && cli
->sign_info
.mandatory_signing
) {
1507 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1508 return NT_STATUS_ACCESS_DENIED
;
1511 if (cli
->protocol
>= PROTOCOL_NT1
) {
1514 cli
->sec_mode
= CVAL(vwv
+ 1, 0);
1515 cli
->max_mux
= SVAL(vwv
+ 1, 1);
1516 cli
->max_xmit
= IVAL(vwv
+ 3, 1);
1517 cli
->sesskey
= IVAL(vwv
+ 7, 1);
1518 cli
->serverzone
= SVALS(vwv
+ 15, 1);
1519 cli
->serverzone
*= 60;
1520 /* this time arrives in real GMT */
1521 ts
= interpret_long_date(((char *)(vwv
+11))+1);
1522 cli
->servertime
= ts
.tv_sec
;
1523 cli
->secblob
= data_blob(bytes
, num_bytes
);
1524 cli
->capabilities
= IVAL(vwv
+ 9, 1);
1525 if (cli
->capabilities
& CAP_RAW_MODE
) {
1526 cli
->readbraw_supported
= True
;
1527 cli
->writebraw_supported
= True
;
1529 /* work out if they sent us a workgroup */
1530 if (!(cli
->capabilities
& CAP_EXTENDED_SECURITY
) &&
1531 smb_buflen(cli
->inbuf
) > 8) {
1532 clistr_pull(cli
->inbuf
, cli
->server_domain
,
1533 bytes
+8, sizeof(cli
->server_domain
),
1535 STR_UNICODE
|STR_NOALIGN
);
1539 * As signing is slow we only turn it on if either the client or
1540 * the server require it. JRA.
1543 if (cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_REQUIRED
) {
1544 /* Fail if server says signing is mandatory and we don't want to support it. */
1545 if (!cli
->sign_info
.allow_smb_signing
) {
1546 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1547 return NT_STATUS_ACCESS_DENIED
;
1549 cli
->sign_info
.negotiated_smb_signing
= True
;
1550 cli
->sign_info
.mandatory_signing
= True
;
1551 } else if (cli
->sign_info
.mandatory_signing
&& cli
->sign_info
.allow_smb_signing
) {
1552 /* Fail if client says signing is mandatory and the server doesn't support it. */
1553 if (!(cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_ENABLED
)) {
1554 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1555 return NT_STATUS_ACCESS_DENIED
;
1557 cli
->sign_info
.negotiated_smb_signing
= True
;
1558 cli
->sign_info
.mandatory_signing
= True
;
1559 } else if (cli
->sec_mode
& NEGOTIATE_SECURITY_SIGNATURES_ENABLED
) {
1560 cli
->sign_info
.negotiated_smb_signing
= True
;
1563 if (cli
->capabilities
& (CAP_LARGE_READX
|CAP_LARGE_WRITEX
)) {
1564 SAFE_FREE(cli
->outbuf
);
1565 SAFE_FREE(cli
->inbuf
);
1566 cli
->outbuf
= (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE
+LARGE_WRITEX_HDR_SIZE
+SAFETY_MARGIN
);
1567 cli
->inbuf
= (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE
+LARGE_WRITEX_HDR_SIZE
+SAFETY_MARGIN
);
1568 cli
->bufsize
= CLI_SAMBA_MAX_LARGE_READX_SIZE
+ LARGE_WRITEX_HDR_SIZE
;
1571 } else if (cli
->protocol
>= PROTOCOL_LANMAN1
) {
1572 cli
->use_spnego
= False
;
1573 cli
->sec_mode
= SVAL(vwv
+ 1, 0);
1574 cli
->max_xmit
= SVAL(vwv
+ 2, 0);
1575 cli
->max_mux
= SVAL(vwv
+ 3, 0);
1576 cli
->sesskey
= IVAL(vwv
+ 6, 0);
1577 cli
->serverzone
= SVALS(vwv
+ 10, 0);
1578 cli
->serverzone
*= 60;
1579 /* this time is converted to GMT by make_unix_date */
1580 cli
->servertime
= cli_make_unix_date(
1581 cli
, (char *)(vwv
+ 8));
1582 cli
->readbraw_supported
= ((SVAL(vwv
+ 5, 0) & 0x1) != 0);
1583 cli
->writebraw_supported
= ((SVAL(vwv
+ 5, 0) & 0x2) != 0);
1584 cli
->secblob
= data_blob(bytes
, num_bytes
);
1586 /* the old core protocol */
1587 cli
->use_spnego
= False
;
1589 cli
->serverzone
= get_time_zone(time(NULL
));
1592 cli
->max_xmit
= MIN(cli
->max_xmit
, CLI_BUFFER_SIZE
);
1594 /* a way to force ascii SMB */
1595 if (getenv("CLI_FORCE_ASCII"))
1596 cli
->capabilities
&= ~CAP_UNICODE
;
1598 return NT_STATUS_OK
;
1601 NTSTATUS
cli_negprot(struct cli_state
*cli
)
1603 TALLOC_CTX
*frame
= talloc_stackframe();
1604 struct event_context
*ev
;
1605 struct async_req
*req
;
1606 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1608 if (cli
->fd_event
!= NULL
) {
1610 * Can't use sync call while an async call is in flight
1612 cli_set_error(cli
, NT_STATUS_INVALID_PARAMETER
);
1616 ev
= event_context_init(frame
);
1621 req
= cli_negprot_send(frame
, ev
, cli
);
1626 while (req
->state
< ASYNC_REQ_DONE
) {
1627 event_loop_once(ev
);
1630 status
= cli_negprot_recv(req
);
1636 /****************************************************************************
1637 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1638 ****************************************************************************/
1640 bool cli_session_request(struct cli_state
*cli
,
1641 struct nmb_name
*calling
, struct nmb_name
*called
)
1646 /* 445 doesn't have session request */
1647 if (cli
->port
== 445)
1650 memcpy(&(cli
->calling
), calling
, sizeof(*calling
));
1651 memcpy(&(cli
->called
), called
, sizeof(*called
));
1653 /* put in the destination name */
1654 p
= cli
->outbuf
+len
;
1655 name_mangle(cli
->called
.name
, p
, cli
->called
.name_type
);
1659 p
= cli
->outbuf
+len
;
1660 name_mangle(cli
->calling
.name
, p
, cli
->calling
.name_type
);
1663 /* send a session request (RFC 1002) */
1664 /* setup the packet length
1665 * Remove four bytes from the length count, since the length
1666 * field in the NBT Session Service header counts the number
1667 * of bytes which follow. The cli_send_smb() function knows
1668 * about this and accounts for those four bytes.
1672 _smb_setlen(cli
->outbuf
,len
);
1673 SCVAL(cli
->outbuf
,0,0x81);
1676 DEBUG(5,("Sent session request\n"));
1678 if (!cli_receive_smb(cli
))
1681 if (CVAL(cli
->inbuf
,0) == 0x84) {
1682 /* C. Hoch 9/14/95 Start */
1683 /* For information, here is the response structure.
1684 * We do the byte-twiddling to for portability.
1685 struct RetargetResponse{
1687 unsigned char flags;
1693 uint16_t port
= (CVAL(cli
->inbuf
,8)<<8)+CVAL(cli
->inbuf
,9);
1694 struct in_addr dest_ip
;
1697 /* SESSION RETARGET */
1698 putip((char *)&dest_ip
,cli
->inbuf
+4);
1699 in_addr_to_sockaddr_storage(&cli
->dest_ss
, dest_ip
);
1701 status
= open_socket_out(&cli
->dest_ss
, port
,
1702 LONG_CONNECT_TIMEOUT
, &cli
->fd
);
1703 if (!NT_STATUS_IS_OK(status
)) {
1707 DEBUG(3,("Retargeted\n"));
1709 set_socket_options(cli
->fd
, lp_socket_options());
1716 DEBUG(0,("Retarget recursion - failing\n"));
1720 ret
= cli_session_request(cli
, calling
, called
);
1724 } /* C. Hoch 9/14/95 End */
1726 if (CVAL(cli
->inbuf
,0) != 0x82) {
1727 /* This is the wrong place to put the error... JRA. */
1728 cli
->rap_error
= CVAL(cli
->inbuf
,4);
1734 static void smb_sock_connected(struct async_req
*req
)
1736 int *pfd
= (int *)req
->async
.priv
;
1740 status
= open_socket_out_defer_recv(req
, &fd
);
1741 if (NT_STATUS_IS_OK(status
)) {
1746 static NTSTATUS
open_smb_socket(const struct sockaddr_storage
*pss
,
1747 uint16_t *port
, int timeout
, int *pfd
)
1749 struct event_context
*ev
;
1750 struct async_req
*r139
, *r445
;
1756 return open_socket_out(pss
, *port
, timeout
, pfd
);
1759 ev
= event_context_init(talloc_tos());
1761 return NT_STATUS_NO_MEMORY
;
1764 r445
= open_socket_out_defer_send(ev
, ev
, timeval_set(0, 0),
1766 r139
= open_socket_out_defer_send(ev
, ev
, timeval_set(0, 3000),
1768 if ((r445
== NULL
) || (r139
== NULL
)) {
1769 status
= NT_STATUS_NO_MEMORY
;
1772 r445
->async
.fn
= smb_sock_connected
;
1773 r445
->async
.priv
= &fd445
;
1774 r139
->async
.fn
= smb_sock_connected
;
1775 r139
->async
.priv
= &fd139
;
1777 while ((fd139
== -1) && (r139
->state
< ASYNC_REQ_DONE
)
1778 && (fd445
== -1) && (r445
->state
< ASYNC_REQ_DONE
)) {
1779 event_loop_once(ev
);
1782 if ((fd139
!= -1) && (fd445
!= -1)) {
1790 status
= NT_STATUS_OK
;
1796 status
= NT_STATUS_OK
;
1800 status
= open_socket_out_defer_recv(r445
, &fd445
);
1806 /****************************************************************************
1807 Open the client sockets.
1808 ****************************************************************************/
1810 NTSTATUS
cli_connect(struct cli_state
*cli
,
1812 struct sockaddr_storage
*dest_ss
)
1815 int name_type
= 0x20;
1816 TALLOC_CTX
*frame
= talloc_stackframe();
1817 unsigned int num_addrs
= 0;
1819 struct sockaddr_storage
*ss_arr
= NULL
;
1822 /* reasonable default hostname */
1824 host
= STAR_SMBSERVER
;
1827 fstrcpy(cli
->desthost
, host
);
1829 /* allow hostnames of the form NAME#xx and do a netbios lookup */
1830 if ((p
= strchr(cli
->desthost
, '#'))) {
1831 name_type
= strtol(p
+1, NULL
, 16);
1835 if (!dest_ss
|| is_zero_addr((struct sockaddr
*)dest_ss
)) {
1836 NTSTATUS status
=resolve_name_list(frame
,
1841 if (!NT_STATUS_IS_OK(status
)) {
1843 return NT_STATUS_BAD_NETWORK_NAME
;
1847 ss_arr
= TALLOC_P(frame
, struct sockaddr_storage
);
1850 return NT_STATUS_NO_MEMORY
;
1855 for (i
= 0; i
< num_addrs
; i
++) {
1856 cli
->dest_ss
= ss_arr
[i
];
1857 if (getenv("LIBSMB_PROG")) {
1858 cli
->fd
= sock_exec(getenv("LIBSMB_PROG"));
1860 uint16_t port
= cli
->port
;
1862 status
= open_smb_socket(&cli
->dest_ss
, &port
,
1863 cli
->timeout
, &cli
->fd
);
1864 if (NT_STATUS_IS_OK(status
)) {
1868 if (cli
->fd
== -1) {
1869 char addr
[INET6_ADDRSTRLEN
];
1870 print_sockaddr(addr
, sizeof(addr
), &ss_arr
[i
]);
1871 DEBUG(2,("Error connecting to %s (%s)\n",
1872 dest_ss
?addr
:host
,strerror(errno
)));
1874 /* Exit from loop on first connection. */
1879 if (cli
->fd
== -1) {
1881 return map_nt_error_from_unix(errno
);
1885 *dest_ss
= cli
->dest_ss
;
1888 set_socket_options(cli
->fd
, lp_socket_options());
1891 return NT_STATUS_OK
;
1895 establishes a connection to after the negprot.
1896 @param output_cli A fully initialised cli structure, non-null only on success
1897 @param dest_host The netbios name of the remote host
1898 @param dest_ss (optional) The the destination IP, NULL for name based lookup
1899 @param port (optional) The destination port (0 for default)
1900 @param retry bool. Did this connection fail with a retryable error ?
1903 NTSTATUS
cli_start_connection(struct cli_state
**output_cli
,
1904 const char *my_name
,
1905 const char *dest_host
,
1906 struct sockaddr_storage
*dest_ss
, int port
,
1907 int signing_state
, int flags
,
1911 struct nmb_name calling
;
1912 struct nmb_name called
;
1913 struct cli_state
*cli
;
1914 struct sockaddr_storage ss
;
1920 my_name
= global_myname();
1922 if (!(cli
= cli_initialise())) {
1923 return NT_STATUS_NO_MEMORY
;
1926 make_nmb_name(&calling
, my_name
, 0x0);
1927 make_nmb_name(&called
, dest_host
, 0x20);
1929 cli_set_port(cli
, port
);
1930 cli_set_timeout(cli
, 10000); /* 10 seconds. */
1940 DEBUG(3,("Connecting to host=%s\n", dest_host
));
1942 nt_status
= cli_connect(cli
, dest_host
, &ss
);
1943 if (!NT_STATUS_IS_OK(nt_status
)) {
1944 char addr
[INET6_ADDRSTRLEN
];
1945 print_sockaddr(addr
, sizeof(addr
), &ss
);
1946 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
1947 nmb_namestr(&called
), addr
, nt_errstr(nt_status
) ));
1955 if (!cli_session_request(cli
, &calling
, &called
)) {
1957 DEBUG(1,("session request to %s failed (%s)\n",
1958 called
.name
, cli_errstr(cli
)));
1959 if ((p
=strchr(called
.name
, '.')) && !is_ipaddress(called
.name
)) {
1963 if (strcmp(called
.name
, STAR_SMBSERVER
)) {
1964 make_nmb_name(&called
, STAR_SMBSERVER
, 0x20);
1967 return NT_STATUS_BAD_NETWORK_NAME
;
1970 cli_setup_signing_state(cli
, signing_state
);
1972 if (flags
& CLI_FULL_CONNECTION_DONT_SPNEGO
)
1973 cli
->use_spnego
= False
;
1974 else if (flags
& CLI_FULL_CONNECTION_USE_KERBEROS
)
1975 cli
->use_kerberos
= True
;
1977 if ((flags
& CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS
) &&
1978 cli
->use_kerberos
) {
1979 cli
->fallback_after_kerberos
= true;
1982 nt_status
= cli_negprot(cli
);
1983 if (!NT_STATUS_IS_OK(nt_status
)) {
1984 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status
)));
1990 return NT_STATUS_OK
;
1995 establishes a connection right up to doing tconX, password specified.
1996 @param output_cli A fully initialised cli structure, non-null only on success
1997 @param dest_host The netbios name of the remote host
1998 @param dest_ip (optional) The the destination IP, NULL for name based lookup
1999 @param port (optional) The destination port (0 for default)
2000 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2001 @param service_type The 'type' of serivice.
2002 @param user Username, unix string
2003 @param domain User's domain
2004 @param password User's password, unencrypted unix string.
2005 @param retry bool. Did this connection fail with a retryable error ?
2008 NTSTATUS
cli_full_connection(struct cli_state
**output_cli
,
2009 const char *my_name
,
2010 const char *dest_host
,
2011 struct sockaddr_storage
*dest_ss
, int port
,
2012 const char *service
, const char *service_type
,
2013 const char *user
, const char *domain
,
2014 const char *password
, int flags
,
2019 struct cli_state
*cli
= NULL
;
2020 int pw_len
= password
? strlen(password
)+1 : 0;
2024 if (password
== NULL
) {
2028 nt_status
= cli_start_connection(&cli
, my_name
, dest_host
,
2029 dest_ss
, port
, signing_state
,
2032 if (!NT_STATUS_IS_OK(nt_status
)) {
2036 nt_status
= cli_session_setup(cli
, user
, password
, pw_len
, password
,
2038 if (!NT_STATUS_IS_OK(nt_status
)) {
2040 if (!(flags
& CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK
)) {
2041 DEBUG(1,("failed session setup with %s\n",
2042 nt_errstr(nt_status
)));
2047 nt_status
= cli_session_setup(cli
, "", "", 0, "", 0, domain
);
2048 if (!NT_STATUS_IS_OK(nt_status
)) {
2049 DEBUG(1,("anonymous failed session setup with %s\n",
2050 nt_errstr(nt_status
)));
2057 nt_status
= cli_tcon_andx(cli
, service
, service_type
, password
,
2059 if (!NT_STATUS_IS_OK(nt_status
)) {
2060 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status
)));
2062 if (NT_STATUS_IS_OK(nt_status
)) {
2063 nt_status
= NT_STATUS_UNSUCCESSFUL
;
2069 cli_init_creds(cli
, user
, domain
, password
);
2072 return NT_STATUS_OK
;
2075 /****************************************************************************
2076 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2077 ****************************************************************************/
2079 bool attempt_netbios_session_request(struct cli_state
**ppcli
, const char *srchost
, const char *desthost
,
2080 struct sockaddr_storage
*pdest_ss
)
2082 struct nmb_name calling
, called
;
2084 make_nmb_name(&calling
, srchost
, 0x0);
2087 * If the called name is an IP address
2088 * then use *SMBSERVER immediately.
2091 if(is_ipaddress(desthost
)) {
2092 make_nmb_name(&called
, STAR_SMBSERVER
, 0x20);
2094 make_nmb_name(&called
, desthost
, 0x20);
2097 if (!cli_session_request(*ppcli
, &calling
, &called
)) {
2099 struct nmb_name smbservername
;
2101 make_nmb_name(&smbservername
, STAR_SMBSERVER
, 0x20);
2104 * If the name wasn't *SMBSERVER then
2105 * try with *SMBSERVER if the first name fails.
2108 if (nmb_name_equal(&called
, &smbservername
)) {
2111 * The name used was *SMBSERVER, don't bother with another name.
2114 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2115 with error %s.\n", desthost
, cli_errstr(*ppcli
) ));
2120 cli_shutdown(*ppcli
);
2122 *ppcli
= cli_initialise();
2124 /* Out of memory... */
2128 status
= cli_connect(*ppcli
, desthost
, pdest_ss
);
2129 if (!NT_STATUS_IS_OK(status
) ||
2130 !cli_session_request(*ppcli
, &calling
, &smbservername
)) {
2131 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2132 name *SMBSERVER with error %s\n", desthost
, cli_errstr(*ppcli
) ));
2140 /****************************************************************************
2141 Send an old style tcon.
2142 ****************************************************************************/
2143 NTSTATUS
cli_raw_tcon(struct cli_state
*cli
,
2144 const char *service
, const char *pass
, const char *dev
,
2145 uint16
*max_xmit
, uint16
*tid
)
2149 if (!lp_client_plaintext_auth() && (*pass
)) {
2150 DEBUG(1, ("Server requested plaintext password but 'client "
2151 "plaintext auth' is disabled\n"));
2152 return NT_STATUS_ACCESS_DENIED
;
2155 memset(cli
->outbuf
,'\0',smb_size
);
2156 memset(cli
->inbuf
,'\0',smb_size
);
2158 cli_set_message(cli
->outbuf
, 0, 0, True
);
2159 SCVAL(cli
->outbuf
,smb_com
,SMBtcon
);
2160 cli_setup_packet(cli
);
2162 p
= smb_buf(cli
->outbuf
);
2163 *p
++ = 4; p
+= clistr_push(cli
, p
, service
, -1, STR_TERMINATE
| STR_NOALIGN
);
2164 *p
++ = 4; p
+= clistr_push(cli
, p
, pass
, -1, STR_TERMINATE
| STR_NOALIGN
);
2165 *p
++ = 4; p
+= clistr_push(cli
, p
, dev
, -1, STR_TERMINATE
| STR_NOALIGN
);
2167 cli_setup_bcc(cli
, p
);
2170 if (!cli_receive_smb(cli
)) {
2171 return NT_STATUS_UNEXPECTED_NETWORK_ERROR
;
2174 if (cli_is_error(cli
)) {
2175 return cli_nt_error(cli
);
2178 *max_xmit
= SVAL(cli
->inbuf
, smb_vwv0
);
2179 *tid
= SVAL(cli
->inbuf
, smb_vwv1
);
2181 return NT_STATUS_OK
;
2184 /* Return a cli_state pointing at the IPC$ share for the given server */
2186 struct cli_state
*get_ipc_connect(char *server
,
2187 struct sockaddr_storage
*server_ss
,
2188 const struct user_auth_info
*user_info
)
2190 struct cli_state
*cli
;
2192 uint32_t flags
= CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK
;
2194 if (user_info
->use_kerberos
) {
2195 flags
|= CLI_FULL_CONNECTION_USE_KERBEROS
;
2198 nt_status
= cli_full_connection(&cli
, NULL
, server
, server_ss
, 0, "IPC$", "IPC",
2199 user_info
->username
? user_info
->username
: "",
2201 user_info
->password
? user_info
->password
: "",
2205 if (NT_STATUS_IS_OK(nt_status
)) {
2207 } else if (is_ipaddress(server
)) {
2208 /* windows 9* needs a correct NMB name for connections */
2209 fstring remote_name
;
2211 if (name_status_find("*", 0, 0, server_ss
, remote_name
)) {
2212 cli
= get_ipc_connect(remote_name
, server_ss
, user_info
);
2221 * Given the IP address of a master browser on the network, return its
2222 * workgroup and connect to it.
2224 * This function is provided to allow additional processing beyond what
2225 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2226 * browsers and obtain each master browsers' list of domains (in case the
2227 * first master browser is recently on the network and has not yet
2228 * synchronized with other master browsers and therefore does not yet have the
2229 * entire network browse list)
2232 struct cli_state
*get_ipc_connect_master_ip(TALLOC_CTX
*ctx
,
2233 struct ip_service
*mb_ip
,
2234 const struct user_auth_info
*user_info
,
2235 char **pp_workgroup_out
)
2237 char addr
[INET6_ADDRSTRLEN
];
2239 struct cli_state
*cli
;
2240 struct sockaddr_storage server_ss
;
2242 *pp_workgroup_out
= NULL
;
2244 print_sockaddr(addr
, sizeof(addr
), &mb_ip
->ss
);
2245 DEBUG(99, ("Looking up name of master browser %s\n",
2249 * Do a name status query to find out the name of the master browser.
2250 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2251 * master browser will not respond to a wildcard query (or, at least,
2252 * an NT4 server acting as the domain master browser will not).
2254 * We might be able to use ONLY the query on MSBROWSE, but that's not
2255 * yet been tested with all Windows versions, so until it is, leave
2256 * the original wildcard query as the first choice and fall back to
2257 * MSBROWSE if the wildcard query fails.
2259 if (!name_status_find("*", 0, 0x1d, &mb_ip
->ss
, name
) &&
2260 !name_status_find(MSBROWSE
, 1, 0x1d, &mb_ip
->ss
, name
)) {
2262 DEBUG(99, ("Could not retrieve name status for %s\n",
2267 if (!find_master_ip(name
, &server_ss
)) {
2268 DEBUG(99, ("Could not find master ip for %s\n", name
));
2272 *pp_workgroup_out
= talloc_strdup(ctx
, name
);
2274 DEBUG(4, ("found master browser %s, %s\n", name
, addr
));
2276 print_sockaddr(addr
, sizeof(addr
), &server_ss
);
2277 cli
= get_ipc_connect(addr
, &server_ss
, user_info
);
2283 * Return the IP address and workgroup of a master browser on the network, and
2287 struct cli_state
*get_ipc_connect_master_ip_bcast(TALLOC_CTX
*ctx
,
2288 const struct user_auth_info
*user_info
,
2289 char **pp_workgroup_out
)
2291 struct ip_service
*ip_list
;
2292 struct cli_state
*cli
;
2295 *pp_workgroup_out
= NULL
;
2297 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2299 /* Go looking for workgroups by broadcasting on the local network */
2301 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE
, 1, &ip_list
,
2303 DEBUG(99, ("No master browsers responded\n"));
2307 for (i
= 0; i
< count
; i
++) {
2308 char addr
[INET6_ADDRSTRLEN
];
2309 print_sockaddr(addr
, sizeof(addr
), &ip_list
[i
].ss
);
2310 DEBUG(99, ("Found master browser %s\n", addr
));
2312 cli
= get_ipc_connect_master_ip(ctx
, &ip_list
[i
],
2313 user_info
, pp_workgroup_out
);