2 Unix SMB/CIFS implementation.
3 client connect/disconnect routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Andrew Bartlett 2001-2003
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "../libcli/auth/libcli_auth.h"
28 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
29 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
30 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
31 {PROTOCOL_LANMAN1, "LANMAN1.0"},
32 {PROTOCOL_LANMAN2, "LM1.2X002"},
33 {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
34 {PROTOCOL_LANMAN2, "LANMAN2.1"},
35 {PROTOCOL_LANMAN2, "Samba"},
36 {PROTOCOL_NT1, "NT LANMAN 1.0"},
37 {PROTOCOL_NT1, "NT LM 0.12"},
40 #define STAR_SMBSERVER "*SMBSERVER"
43 * Set the user session key for a connection
44 * @param cli The cli structure to add it too
45 * @param session_key The session key used. (A copy of this is taken for the cli struct)
49 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
51 cli->user_session_key = data_blob(session_key.data, session_key.length);
54 /****************************************************************************
55 Do an old lanman2 style session setup.
56 ****************************************************************************/
58 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
60 const char *pass, size_t passlen,
61 const char *workgroup)
63 DATA_BLOB session_key = data_blob_null;
64 DATA_BLOB lm_response = data_blob_null;
69 if (passlen > sizeof(pword)-1) {
70 return NT_STATUS_INVALID_PARAMETER;
73 /* LANMAN servers predate NT status codes and Unicode and ignore those
74 smb flags so we must disable the corresponding default capabilities
75 that would otherwise cause the Unicode and NT Status flags to be
76 set (and even returned by the server) */
78 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
80 /* if in share level security then don't send a password now */
81 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
84 if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
85 /* Encrypted mode needed, and non encrypted password supplied. */
86 lm_response = data_blob(NULL, 24);
87 if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) {
88 DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
89 return NT_STATUS_ACCESS_DENIED;
91 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
92 /* Encrypted mode needed, and encrypted password supplied. */
93 lm_response = data_blob(pass, passlen);
94 } else if (passlen > 0) {
95 /* Plaintext mode needed, assume plaintext supplied. */
96 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
97 lm_response = data_blob(pass, passlen);
100 /* send a session setup command */
101 memset(cli->outbuf,'\0',smb_size);
102 cli_set_message(cli->outbuf,10, 0, True);
103 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
104 cli_setup_packet(cli);
106 SCVAL(cli->outbuf,smb_vwv0,0xFF);
107 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
108 SSVAL(cli->outbuf,smb_vwv3,2);
109 SSVAL(cli->outbuf,smb_vwv4,1);
110 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
111 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
113 p = smb_buf(cli->outbuf);
114 memcpy(p,lm_response.data,lm_response.length);
115 p += lm_response.length;
116 p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
117 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
118 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
119 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
120 cli_setup_bcc(cli, p);
122 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
123 return cli_nt_error(cli);
126 show_msg(cli->inbuf);
128 if (cli_is_error(cli)) {
129 return cli_nt_error(cli);
132 /* use the returned vuid from now on */
133 cli->vuid = SVAL(cli->inbuf,smb_uid);
134 status = cli_set_username(cli, user);
135 if (!NT_STATUS_IS_OK(status)) {
139 if (session_key.data) {
140 /* Have plaintext orginal */
141 cli_set_session_key(cli, session_key);
147 /****************************************************************************
148 Work out suitable capabilities to offer the server.
149 ****************************************************************************/
151 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
153 uint32 capabilities = CAP_NT_SMBS;
155 if (!cli->force_dos_errors)
156 capabilities |= CAP_STATUS32;
158 if (cli->use_level_II_oplocks)
159 capabilities |= CAP_LEVEL_II_OPLOCKS;
161 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
165 /****************************************************************************
166 Do a NT1 guest session setup.
167 ****************************************************************************/
169 struct cli_session_setup_guest_state {
170 struct cli_state *cli;
175 static void cli_session_setup_guest_done(struct tevent_req *subreq);
177 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
178 struct event_context *ev,
179 struct cli_state *cli,
180 struct tevent_req **psmbreq)
182 struct tevent_req *req, *subreq;
183 struct cli_session_setup_guest_state *state;
187 req = tevent_req_create(mem_ctx, &state,
188 struct cli_session_setup_guest_state);
195 SCVAL(vwv+0, 0, 0xFF);
198 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
200 SSVAL(vwv+4, 0, cli->pid);
201 SIVAL(vwv+5, 0, cli->sesskey);
206 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
208 bytes = talloc_array(state, uint8_t, 0);
210 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
212 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
214 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
215 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
222 state->bytes.iov_base = (void *)bytes;
223 state->bytes.iov_len = talloc_get_size(bytes);
225 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
227 if (subreq == NULL) {
231 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
236 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
237 struct event_context *ev,
238 struct cli_state *cli)
240 struct tevent_req *req, *subreq;
243 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
248 status = cli_smb_req_send(subreq);
249 if (NT_STATUS_IS_OK(status)) {
250 tevent_req_nterror(req, status);
251 return tevent_req_post(req, ev);
256 static void cli_session_setup_guest_done(struct tevent_req *subreq)
258 struct tevent_req *req = tevent_req_callback_data(
259 subreq, struct tevent_req);
260 struct cli_session_setup_guest_state *state = tevent_req_data(
261 req, struct cli_session_setup_guest_state);
262 struct cli_state *cli = state->cli;
269 status = cli_smb_recv(subreq, 0, NULL, NULL, &num_bytes, &bytes);
270 if (!NT_STATUS_IS_OK(status)) {
272 tevent_req_nterror(req, status);
276 inbuf = (char *)cli_smb_inbuf(subreq);
279 cli->vuid = SVAL(inbuf, smb_uid);
281 p += clistr_pull(inbuf, cli->server_os, (char *)p, sizeof(fstring),
282 bytes+num_bytes-p, STR_TERMINATE);
283 p += clistr_pull(inbuf, cli->server_type, (char *)p, sizeof(fstring),
284 bytes+num_bytes-p, STR_TERMINATE);
285 p += clistr_pull(inbuf, cli->server_domain, (char *)p, sizeof(fstring),
286 bytes+num_bytes-p, STR_TERMINATE);
288 if (strstr(cli->server_type, "Samba")) {
289 cli->is_samba = True;
294 status = cli_set_username(cli, "");
295 if (!NT_STATUS_IS_OK(status)) {
296 tevent_req_nterror(req, status);
299 tevent_req_done(req);
302 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
304 return tevent_req_simple_recv_ntstatus(req);
307 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
309 TALLOC_CTX *frame = talloc_stackframe();
310 struct event_context *ev;
311 struct tevent_req *req;
312 NTSTATUS status = NT_STATUS_OK;
314 if (cli_has_async_calls(cli)) {
316 * Can't use sync call while an async call is in flight
318 status = NT_STATUS_INVALID_PARAMETER;
322 ev = event_context_init(frame);
324 status = NT_STATUS_NO_MEMORY;
328 req = cli_session_setup_guest_send(frame, ev, cli);
330 status = NT_STATUS_NO_MEMORY;
334 if (!tevent_req_poll(req, ev)) {
335 status = map_nt_error_from_unix(errno);
339 status = cli_session_setup_guest_recv(req);
342 if (!NT_STATUS_IS_OK(status)) {
343 cli_set_error(cli, status);
348 /****************************************************************************
349 Do a NT1 plaintext session setup.
350 ****************************************************************************/
352 static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
353 const char *user, const char *pass,
354 const char *workgroup)
356 uint32 capabilities = cli_session_setup_capabilities(cli);
361 fstr_sprintf( lanman, "Samba %s", samba_version_string());
363 memset(cli->outbuf, '\0', smb_size);
364 cli_set_message(cli->outbuf,13,0,True);
365 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
366 cli_setup_packet(cli);
368 SCVAL(cli->outbuf,smb_vwv0,0xFF);
369 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
370 SSVAL(cli->outbuf,smb_vwv3,2);
371 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
372 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
373 SSVAL(cli->outbuf,smb_vwv8,0);
374 SIVAL(cli->outbuf,smb_vwv11,capabilities);
375 p = smb_buf(cli->outbuf);
377 /* check wether to send the ASCII or UNICODE version of the password */
379 if ( (capabilities & CAP_UNICODE) == 0 ) {
380 p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
381 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
384 /* For ucs2 passwords clistr_push calls ucs2_align, which causes
385 * the space taken by the unicode password to be one byte too
386 * long (as we're on an odd byte boundary here). Reduce the
387 * count by 1 to cope with this. Fixes smbclient against NetApp
388 * servers which can't cope. Fix from
389 * bryan.kolodziej@allenlund.com in bug #3840.
391 p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
392 SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))-1);
395 p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
396 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
397 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
398 p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
399 cli_setup_bcc(cli, p);
401 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
402 return cli_nt_error(cli);
405 show_msg(cli->inbuf);
407 if (cli_is_error(cli)) {
408 return cli_nt_error(cli);
411 cli->vuid = SVAL(cli->inbuf,smb_uid);
412 p = smb_buf(cli->inbuf);
413 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
415 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
417 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
419 status = cli_set_username(cli, user);
420 if (!NT_STATUS_IS_OK(status)) {
423 if (strstr(cli->server_type, "Samba")) {
424 cli->is_samba = True;
430 /****************************************************************************
431 do a NT1 NTLM/LM encrypted session setup - for when extended security
433 @param cli client state to create do session setup on
435 @param pass *either* cleartext password (passlen !=24) or LM response.
436 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
437 @param workgroup The user's domain.
438 ****************************************************************************/
440 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
441 const char *pass, size_t passlen,
442 const char *ntpass, size_t ntpasslen,
443 const char *workgroup)
445 uint32 capabilities = cli_session_setup_capabilities(cli);
446 DATA_BLOB lm_response = data_blob_null;
447 DATA_BLOB nt_response = data_blob_null;
448 DATA_BLOB session_key = data_blob_null;
454 /* do nothing - guest login */
455 } else if (passlen != 24) {
456 if (lp_client_ntlmv2_auth()) {
457 DATA_BLOB server_chal;
458 DATA_BLOB names_blob;
459 server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
461 /* note that the 'workgroup' here is a best guess - we don't know
462 the server's domain at this point. The 'server name' is also
465 names_blob = NTLMv2_generate_names_blob(NULL, cli->called.name, workgroup);
467 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass, &server_chal,
469 &lm_response, &nt_response, NULL, &session_key)) {
470 data_blob_free(&names_blob);
471 data_blob_free(&server_chal);
472 return NT_STATUS_ACCESS_DENIED;
474 data_blob_free(&names_blob);
475 data_blob_free(&server_chal);
479 E_md4hash(pass, nt_hash);
482 nt_response = data_blob_null;
484 nt_response = data_blob(NULL, 24);
485 SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
487 /* non encrypted password supplied. Ignore ntpass. */
488 if (lp_client_lanman_auth()) {
489 lm_response = data_blob(NULL, 24);
490 if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) {
491 /* Oops, the LM response is invalid, just put
492 the NT response there instead */
493 data_blob_free(&lm_response);
494 lm_response = data_blob(nt_response.data, nt_response.length);
497 /* LM disabled, place NT# in LM field instead */
498 lm_response = data_blob(nt_response.data, nt_response.length);
501 session_key = data_blob(NULL, 16);
503 E_deshash(pass, session_key.data);
504 memset(&session_key.data[8], '\0', 8);
506 SMBsesskeygen_ntv1(nt_hash, session_key.data);
509 cli_temp_set_signing(cli);
511 /* pre-encrypted password supplied. Only used for
512 security=server, can't do
513 signing because we don't have original key */
515 lm_response = data_blob(pass, passlen);
516 nt_response = data_blob(ntpass, ntpasslen);
519 /* send a session setup command */
520 memset(cli->outbuf,'\0',smb_size);
522 cli_set_message(cli->outbuf,13,0,True);
523 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
524 cli_setup_packet(cli);
526 SCVAL(cli->outbuf,smb_vwv0,0xFF);
527 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
528 SSVAL(cli->outbuf,smb_vwv3,2);
529 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
530 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
531 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
532 SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
533 SIVAL(cli->outbuf,smb_vwv11,capabilities);
534 p = smb_buf(cli->outbuf);
535 if (lm_response.length) {
536 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
538 if (nt_response.length) {
539 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
541 p += clistr_push(cli, p, user, -1, STR_TERMINATE);
543 /* Upper case here might help some NTLMv2 implementations */
544 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
545 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
546 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
547 cli_setup_bcc(cli, p);
549 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
550 result = cli_nt_error(cli);
554 /* show_msg(cli->inbuf); */
556 if (cli_is_error(cli)) {
557 result = cli_nt_error(cli);
562 ok = cli_simple_set_signing(cli, session_key, lm_response);
564 ok = cli_simple_set_signing(cli, session_key, nt_response);
567 if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
568 result = NT_STATUS_ACCESS_DENIED;
573 /* use the returned vuid from now on */
574 cli->vuid = SVAL(cli->inbuf,smb_uid);
576 p = smb_buf(cli->inbuf);
577 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
579 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
581 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
584 if (strstr(cli->server_type, "Samba")) {
585 cli->is_samba = True;
588 result = cli_set_username(cli, user);
589 if (!NT_STATUS_IS_OK(result)) {
593 if (session_key.data) {
594 /* Have plaintext orginal */
595 cli_set_session_key(cli, session_key);
598 result = NT_STATUS_OK;
600 data_blob_free(&lm_response);
601 data_blob_free(&nt_response);
602 data_blob_free(&session_key);
606 /****************************************************************************
607 Send a extended security session setup blob
608 ****************************************************************************/
610 static bool cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob)
612 uint32 capabilities = cli_session_setup_capabilities(cli);
615 capabilities |= CAP_EXTENDED_SECURITY;
617 /* send a session setup command */
618 memset(cli->outbuf,'\0',smb_size);
620 cli_set_message(cli->outbuf,12,0,True);
621 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
623 cli_setup_packet(cli);
625 SCVAL(cli->outbuf,smb_vwv0,0xFF);
626 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
627 SSVAL(cli->outbuf,smb_vwv3,2);
628 SSVAL(cli->outbuf,smb_vwv4,1);
629 SIVAL(cli->outbuf,smb_vwv5,0);
630 SSVAL(cli->outbuf,smb_vwv7,blob.length);
631 SIVAL(cli->outbuf,smb_vwv10,capabilities);
632 p = smb_buf(cli->outbuf);
633 memcpy(p, blob.data, blob.length);
635 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
636 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
637 cli_setup_bcc(cli, p);
638 return cli_send_smb(cli);
641 /****************************************************************************
642 Send a extended security session setup blob, returning a reply blob.
643 ****************************************************************************/
645 static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
647 DATA_BLOB blob2 = data_blob_null;
651 if (!cli_receive_smb(cli))
654 show_msg(cli->inbuf);
656 if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli),
657 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
661 /* use the returned vuid from now on */
662 cli->vuid = SVAL(cli->inbuf,smb_uid);
664 p = smb_buf(cli->inbuf);
666 blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
669 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
672 /* w2k with kerberos doesn't properly null terminate this field */
673 len = smb_bufrem(cli->inbuf, p);
674 if (p + len < cli->inbuf + cli->bufsize+SAFETY_MARGIN - 2) {
675 char *end_of_buf = p + len;
678 /* Now it's null terminated. */
679 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
682 * See if there's another string. If so it's the
683 * server domain (part of the 'standard' Samba
686 if (p < end_of_buf) {
687 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
692 * No room to null terminate so we can't see if there
693 * is another string (server_domain) afterwards.
695 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
702 /****************************************************************************
703 Send a extended security session setup blob, returning a reply blob.
704 ****************************************************************************/
706 /* The following is calculated from :
708 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
709 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
713 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
715 static bool cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
717 int32 remaining = blob.length;
719 DATA_BLOB send_blob = data_blob_null;
720 int32 max_blob_size = 0;
721 DATA_BLOB receive_blob = data_blob_null;
723 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
724 DEBUG(0,("cli_session_setup_blob: cli->max_xmit too small "
725 "(was %u, need minimum %u)\n",
726 (unsigned int)cli->max_xmit,
727 BASE_SESSSETUP_BLOB_PACKET_SIZE));
728 cli_set_nt_error(cli, NT_STATUS_INVALID_PARAMETER);
732 max_blob_size = cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE;
734 while ( remaining > 0) {
735 if (remaining >= max_blob_size) {
736 send_blob.length = max_blob_size;
737 remaining -= max_blob_size;
739 send_blob.length = remaining;
743 send_blob.data = &blob.data[cur];
744 cur += send_blob.length;
746 DEBUG(10, ("cli_session_setup_blob: Remaining (%u) sending (%u) current (%u)\n",
747 (unsigned int)remaining,
748 (unsigned int)send_blob.length,
749 (unsigned int)cur ));
751 if (!cli_session_setup_blob_send(cli, send_blob)) {
752 DEBUG(0, ("cli_session_setup_blob: send failed\n"));
756 receive_blob = cli_session_setup_blob_receive(cli);
757 data_blob_free(&receive_blob);
759 if (cli_is_error(cli) &&
760 !NT_STATUS_EQUAL( cli_get_nt_error(cli),
761 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
762 DEBUG(0, ("cli_session_setup_blob: receive failed "
763 "(%s)\n", nt_errstr(cli_get_nt_error(cli))));
772 /****************************************************************************
773 Use in-memory credentials cache
774 ****************************************************************************/
776 static void use_in_memory_ccache(void) {
777 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
780 /****************************************************************************
781 Do a spnego/kerberos encrypted session setup.
782 ****************************************************************************/
784 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
786 DATA_BLOB negTokenTarg;
787 DATA_BLOB session_key_krb5;
791 cli_temp_set_signing(cli);
793 DEBUG(2,("Doing kerberos session setup\n"));
795 /* generate the encapsulated kerberos5 ticket */
796 rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5, 0, NULL);
799 DEBUG(1, ("cli_session_setup_kerberos: spnego_gen_negTokenTarg failed: %s\n",
801 return ADS_ERROR_KRB5(rc);
805 file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
808 if (!cli_session_setup_blob(cli, negTokenTarg)) {
809 nt_status = cli_nt_error(cli);
813 if (cli_is_error(cli)) {
814 nt_status = cli_nt_error(cli);
815 if (NT_STATUS_IS_OK(nt_status)) {
816 nt_status = NT_STATUS_UNSUCCESSFUL;
821 cli_set_session_key(cli, session_key_krb5);
823 if (cli_simple_set_signing(
824 cli, session_key_krb5, data_blob_null)) {
826 if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
827 nt_status = NT_STATUS_ACCESS_DENIED;
832 data_blob_free(&negTokenTarg);
833 data_blob_free(&session_key_krb5);
835 return ADS_ERROR_NT(NT_STATUS_OK);
838 data_blob_free(&negTokenTarg);
839 data_blob_free(&session_key_krb5);
841 return ADS_ERROR_NT(nt_status);
843 #endif /* HAVE_KRB5 */
846 /****************************************************************************
847 Do a spnego/NTLMSSP encrypted session setup.
848 ****************************************************************************/
850 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
851 const char *pass, const char *domain)
853 struct ntlmssp_state *ntlmssp_state;
857 DATA_BLOB blob = data_blob_null;
858 DATA_BLOB blob_in = data_blob_null;
859 DATA_BLOB blob_out = data_blob_null;
861 cli_temp_set_signing(cli);
863 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
866 ntlmssp_want_feature(ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
868 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
871 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
874 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
879 nt_status = ntlmssp_update(ntlmssp_state,
881 data_blob_free(&blob_in);
882 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(nt_status)) {
884 /* and wrap it in a SPNEGO wrapper */
885 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
887 /* wrap it in SPNEGO */
888 msg1 = spnego_gen_auth(blob_out);
891 /* now send that blob on its way */
892 if (!cli_session_setup_blob_send(cli, msg1)) {
893 DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
894 nt_status = NT_STATUS_UNSUCCESSFUL;
896 blob = cli_session_setup_blob_receive(cli);
898 nt_status = cli_nt_error(cli);
899 if (cli_is_error(cli) && NT_STATUS_IS_OK(nt_status)) {
900 if (cli->smb_rw_error == SMB_READ_BAD_SIG) {
901 nt_status = NT_STATUS_ACCESS_DENIED;
903 nt_status = NT_STATUS_UNSUCCESSFUL;
907 data_blob_free(&msg1);
911 if (NT_STATUS_IS_OK(nt_status)) {
912 nt_status = NT_STATUS_UNSUCCESSFUL;
914 } else if ((turn == 1) &&
915 NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
916 DATA_BLOB tmp_blob = data_blob_null;
917 /* the server might give us back two challenges */
918 if (!spnego_parse_challenge(blob, &blob_in,
920 DEBUG(3,("Failed to parse challenges\n"));
921 nt_status = NT_STATUS_INVALID_PARAMETER;
923 data_blob_free(&tmp_blob);
925 if (!spnego_parse_auth_response(blob, nt_status, OID_NTLMSSP,
927 DEBUG(3,("Failed to parse auth response\n"));
928 if (NT_STATUS_IS_OK(nt_status)
929 || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED))
930 nt_status = NT_STATUS_INVALID_PARAMETER;
933 data_blob_free(&blob);
934 data_blob_free(&blob_out);
936 } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
938 data_blob_free(&blob_in);
940 if (NT_STATUS_IS_OK(nt_status)) {
942 if (cli->server_domain[0] == '\0') {
943 fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
945 cli_set_session_key(cli, ntlmssp_state->session_key);
947 if (cli_simple_set_signing(
948 cli, ntlmssp_state->session_key, data_blob_null)) {
950 if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
951 nt_status = NT_STATUS_ACCESS_DENIED;
956 /* we have a reference conter on ntlmssp_state, if we are signing
957 then the state will be kept by the signing engine */
959 ntlmssp_end(&ntlmssp_state);
961 if (!NT_STATUS_IS_OK(nt_status)) {
967 /****************************************************************************
968 Do a spnego encrypted session setup.
970 user_domain: The shortname of the domain the user/machine is a member of.
971 dest_realm: The realm we're connecting to, if NULL we use our default realm.
972 ****************************************************************************/
974 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
975 const char *pass, const char *user_domain,
976 const char * dest_realm)
978 char *principal = NULL;
979 char *OIDs[ASN1_MAX_OIDS];
982 const char *p = NULL;
983 char *account = NULL;
986 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
988 /* the server might not even do spnego */
989 if (cli->secblob.length <= 16) {
990 DEBUG(3,("server didn't supply a full spnego negprot\n"));
995 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
998 /* there is 16 bytes of GUID before the real spnego packet starts */
999 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1001 /* The server sent us the first part of the SPNEGO exchange in the
1002 * negprot reply. It is WRONG to depend on the principal sent in the
1003 * negprot reply, but right now we do it. If we don't receive one,
1004 * we try to best guess, then fall back to NTLM. */
1005 if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
1006 data_blob_free(&blob);
1007 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1009 data_blob_free(&blob);
1011 /* make sure the server understands kerberos */
1012 for (i=0;OIDs[i];i++) {
1014 DEBUG(3,("got OID=%s\n", OIDs[i]));
1016 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1017 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1018 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1019 cli->got_kerberos_mechanism = True;
1021 talloc_free(OIDs[i]);
1024 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1026 status = cli_set_username(cli, user);
1027 if (!NT_STATUS_IS_OK(status)) {
1028 return ADS_ERROR_NT(status);
1032 /* If password is set we reauthenticate to kerberos server
1033 * and do not store results */
1035 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1038 if (pass && *pass) {
1041 use_in_memory_ccache();
1042 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1045 TALLOC_FREE(principal);
1046 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1047 if (cli->fallback_after_kerberos)
1049 return ADS_ERROR_KRB5(ret);
1053 /* If we get a bad principal, try to guess it if
1054 we have a valid host NetBIOS name.
1056 if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1057 TALLOC_FREE(principal);
1060 if (principal == NULL &&
1061 !is_ipaddress(cli->desthost) &&
1062 !strequal(STAR_SMBSERVER,
1065 char *machine = NULL;
1067 DEBUG(3,("cli_session_setup_spnego: got a "
1068 "bad server principal, trying to guess ...\n"));
1070 host = strchr_m(cli->desthost, '.');
1072 machine = SMB_STRNDUP(cli->desthost,
1073 host - cli->desthost);
1075 machine = SMB_STRDUP(cli->desthost);
1077 if (machine == NULL) {
1078 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1082 realm = SMB_STRDUP(dest_realm);
1085 realm = kerberos_get_default_realm_from_ccache();
1087 if (realm && *realm) {
1088 principal = talloc_asprintf(NULL, "%s$@%s",
1093 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1095 DEBUG(3,("cli_session_setup_spnego: guessed "
1096 "server principal=%s\n",
1097 principal ? principal : "<null>"));
1104 rc = cli_session_setup_kerberos(cli, principal,
1106 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1107 TALLOC_FREE(principal);
1114 TALLOC_FREE(principal);
1118 account = talloc_strdup(talloc_tos(), user);
1120 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1123 /* when falling back to ntlmssp while authenticating with a machine
1124 * account strip off the realm - gd */
1126 if ((p = strchr_m(user, '@')) != NULL) {
1127 account[PTR_DIFF(p,user)] = '\0';
1130 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1133 /****************************************************************************
1134 Send a session setup. The username and workgroup is in UNIX character
1135 format and must be converted to DOS codepage format before sending. If the
1136 password is in plaintext, the same should be done.
1137 ****************************************************************************/
1139 NTSTATUS cli_session_setup(struct cli_state *cli,
1141 const char *pass, int passlen,
1142 const char *ntpass, int ntpasslen,
1143 const char *workgroup)
1149 fstrcpy(user2, user);
1158 /* allow for workgroups as part of the username */
1159 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1160 (p=strchr_m(user2,*lp_winbind_separator()))) {
1166 if (cli->protocol < PROTOCOL_LANMAN1) {
1167 return NT_STATUS_OK;
1170 /* now work out what sort of session setup we are going to
1171 do. I have split this into separate functions to make the
1172 flow a bit easier to understand (tridge) */
1174 /* if its an older server then we have to use the older request format */
1176 if (cli->protocol < PROTOCOL_NT1) {
1177 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1178 DEBUG(1, ("Server requested LM password but 'client lanman auth'"
1180 return NT_STATUS_ACCESS_DENIED;
1183 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1184 !lp_client_plaintext_auth() && (*pass)) {
1185 DEBUG(1, ("Server requested plaintext password but "
1186 "'client plaintext auth' is disabled\n"));
1187 return NT_STATUS_ACCESS_DENIED;
1190 return cli_session_setup_lanman2(cli, user, pass, passlen,
1194 /* if no user is supplied then we have to do an anonymous connection.
1195 passwords are ignored */
1197 if (!user || !*user)
1198 return cli_session_setup_guest(cli);
1200 /* if the server is share level then send a plaintext null
1201 password at this point. The password is sent in the tree
1204 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
1205 return cli_session_setup_plaintext(cli, user, "", workgroup);
1207 /* if the server doesn't support encryption then we have to use
1208 plaintext. The second password is ignored */
1210 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1211 if (!lp_client_plaintext_auth() && (*pass)) {
1212 DEBUG(1, ("Server requested plaintext password but "
1213 "'client plaintext auth' is disabled\n"));
1214 return NT_STATUS_ACCESS_DENIED;
1216 return cli_session_setup_plaintext(cli, user, pass, workgroup);
1219 /* if the server supports extended security then use SPNEGO */
1221 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
1222 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
1224 if (!ADS_ERR_OK(status)) {
1225 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1226 return ads_ntstatus(status);
1231 /* otherwise do a NT1 style session setup */
1232 status = cli_session_setup_nt1(cli, user, pass, passlen,
1233 ntpass, ntpasslen, workgroup);
1234 if (!NT_STATUS_IS_OK(status)) {
1235 DEBUG(3,("cli_session_setup: NT1 session setup "
1236 "failed: %s\n", nt_errstr(status)));
1241 if (strstr(cli->server_type, "Samba")) {
1242 cli->is_samba = True;
1245 return NT_STATUS_OK;
1248 /****************************************************************************
1250 *****************************************************************************/
1252 bool cli_ulogoff(struct cli_state *cli)
1254 memset(cli->outbuf,'\0',smb_size);
1255 cli_set_message(cli->outbuf,2,0,True);
1256 SCVAL(cli->outbuf,smb_com,SMBulogoffX);
1257 cli_setup_packet(cli);
1258 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1259 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1262 if (!cli_receive_smb(cli))
1265 if (cli_is_error(cli)) {
1273 /****************************************************************************
1275 ****************************************************************************/
1277 struct cli_tcon_andx_state {
1278 struct cli_state *cli;
1283 static void cli_tcon_andx_done(struct tevent_req *subreq);
1285 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1286 struct event_context *ev,
1287 struct cli_state *cli,
1288 const char *share, const char *dev,
1289 const char *pass, int passlen,
1290 struct tevent_req **psmbreq)
1292 struct tevent_req *req, *subreq;
1293 struct cli_tcon_andx_state *state;
1299 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1306 fstrcpy(cli->share, share);
1308 /* in user level security don't send a password now */
1309 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1312 } else if (pass == NULL) {
1313 DEBUG(1, ("Server not using user level security and no "
1314 "password supplied.\n"));
1318 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1319 *pass && passlen != 24) {
1320 if (!lp_client_lanman_auth()) {
1321 DEBUG(1, ("Server requested LANMAN password "
1322 "(share-level security) but "
1323 "'client lanman auth' is disabled\n"));
1328 * Non-encrypted passwords - convert to DOS codepage before
1332 SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
1334 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1335 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1337 if (!lp_client_plaintext_auth() && (*pass)) {
1338 DEBUG(1, ("Server requested plaintext "
1339 "password but 'client plaintext "
1340 "auth' is disabled\n"));
1345 * Non-encrypted passwords - convert to DOS codepage
1348 passlen = clistr_push(cli, pword, pass, sizeof(pword),
1350 if (passlen == -1) {
1351 DEBUG(1, ("clistr_push(pword) failed\n"));
1356 memcpy(pword, pass, passlen);
1361 SCVAL(vwv+0, 0, 0xFF);
1364 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
1365 SSVAL(vwv+3, 0, passlen);
1368 bytes = (uint8_t *)talloc_memdup(state, pword, passlen);
1370 bytes = talloc_array(state, uint8_t, 0);
1376 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1377 cli->desthost, share);
1382 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
1387 * Add the devicetype
1389 tmp = talloc_strdup_upper(talloc_tos(), dev);
1394 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1397 if (bytes == NULL) {
1402 state->bytes.iov_base = (void *)bytes;
1403 state->bytes.iov_len = talloc_get_size(bytes);
1405 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
1407 if (subreq == NULL) {
1411 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
1416 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1417 return tevent_req_post(req, ev);
1420 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
1421 struct event_context *ev,
1422 struct cli_state *cli,
1423 const char *share, const char *dev,
1424 const char *pass, int passlen)
1426 struct tevent_req *req, *subreq;
1429 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
1434 status = cli_smb_req_send(subreq);
1435 if (!NT_STATUS_IS_OK(status)) {
1436 tevent_req_nterror(req, status);
1437 return tevent_req_post(req, ev);
1442 static void cli_tcon_andx_done(struct tevent_req *subreq)
1444 struct tevent_req *req = tevent_req_callback_data(
1445 subreq, struct tevent_req);
1446 struct cli_tcon_andx_state *state = tevent_req_data(
1447 req, struct cli_tcon_andx_state);
1448 struct cli_state *cli = state->cli;
1449 char *inbuf = (char *)cli_smb_inbuf(subreq);
1456 status = cli_smb_recv(subreq, 0, &wct, &vwv, &num_bytes, &bytes);
1457 if (!NT_STATUS_IS_OK(status)) {
1458 TALLOC_FREE(subreq);
1459 tevent_req_nterror(req, status);
1463 clistr_pull(inbuf, cli->dev, bytes, sizeof(fstring), num_bytes,
1464 STR_TERMINATE|STR_ASCII);
1466 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
1467 /* almost certainly win95 - enable bug fixes */
1472 * Make sure that we have the optional support 16-bit field. WCT > 2.
1473 * Avoids issues when connecting to Win9x boxes sharing files
1476 cli->dfsroot = false;
1478 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
1479 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
1482 cli->cnum = SVAL(inbuf,smb_tid);
1483 tevent_req_done(req);
1486 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
1488 return tevent_req_simple_recv_ntstatus(req);
1491 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
1492 const char *dev, const char *pass, int passlen)
1494 TALLOC_CTX *frame = talloc_stackframe();
1495 struct event_context *ev;
1496 struct tevent_req *req;
1497 NTSTATUS status = NT_STATUS_OK;
1499 if (cli_has_async_calls(cli)) {
1501 * Can't use sync call while an async call is in flight
1503 status = NT_STATUS_INVALID_PARAMETER;
1507 ev = event_context_init(frame);
1509 status = NT_STATUS_NO_MEMORY;
1513 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
1515 status = NT_STATUS_NO_MEMORY;
1519 if (!tevent_req_poll(req, ev)) {
1520 status = map_nt_error_from_unix(errno);
1524 status = cli_tcon_andx_recv(req);
1527 if (!NT_STATUS_IS_OK(status)) {
1528 cli_set_error(cli, status);
1533 /****************************************************************************
1534 Send a tree disconnect.
1535 ****************************************************************************/
1537 bool cli_tdis(struct cli_state *cli)
1539 memset(cli->outbuf,'\0',smb_size);
1540 cli_set_message(cli->outbuf,0,0,True);
1541 SCVAL(cli->outbuf,smb_com,SMBtdis);
1542 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1543 cli_setup_packet(cli);
1546 if (!cli_receive_smb(cli))
1549 if (cli_is_error(cli)) {
1557 /****************************************************************************
1558 Send a negprot command.
1559 ****************************************************************************/
1561 void cli_negprot_sendsync(struct cli_state *cli)
1566 if (cli->protocol < PROTOCOL_NT1)
1567 cli->use_spnego = False;
1569 memset(cli->outbuf,'\0',smb_size);
1571 /* setup the protocol strings */
1572 cli_set_message(cli->outbuf,0,0,True);
1574 p = smb_buf(cli->outbuf);
1575 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1576 if (prots[numprots].prot > cli->protocol) {
1580 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1583 SCVAL(cli->outbuf,smb_com,SMBnegprot);
1584 cli_setup_bcc(cli, p);
1585 cli_setup_packet(cli);
1587 SCVAL(smb_buf(cli->outbuf),0,2);
1592 /****************************************************************************
1593 Send a negprot command.
1594 ****************************************************************************/
1596 struct cli_negprot_state {
1597 struct cli_state *cli;
1600 static void cli_negprot_done(struct tevent_req *subreq);
1602 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
1603 struct event_context *ev,
1604 struct cli_state *cli)
1606 struct tevent_req *req, *subreq;
1607 struct cli_negprot_state *state;
1608 uint8_t *bytes = NULL;
1611 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
1617 if (cli->protocol < PROTOCOL_NT1)
1618 cli->use_spnego = False;
1620 /* setup the protocol strings */
1621 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1623 if (prots[numprots].prot > cli->protocol) {
1626 bytes = (uint8_t *)talloc_append_blob(
1627 state, bytes, data_blob_const(&c, sizeof(c)));
1628 if (tevent_req_nomem(bytes, req)) {
1629 return tevent_req_post(req, ev);
1631 bytes = smb_bytes_push_str(bytes, false,
1632 prots[numprots].name,
1633 strlen(prots[numprots].name)+1,
1635 if (tevent_req_nomem(bytes, req)) {
1636 return tevent_req_post(req, ev);
1640 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
1641 talloc_get_size(bytes), bytes);
1642 if (tevent_req_nomem(subreq, req)) {
1643 return tevent_req_post(req, ev);
1645 tevent_req_set_callback(subreq, cli_negprot_done, req);
1649 static void cli_negprot_done(struct tevent_req *subreq)
1651 struct tevent_req *req = tevent_req_callback_data(
1652 subreq, struct tevent_req);
1653 struct cli_negprot_state *state = tevent_req_data(
1654 req, struct cli_negprot_state);
1655 struct cli_state *cli = state->cli;
1663 status = cli_smb_recv(subreq, 1, &wct, &vwv, &num_bytes, &bytes);
1664 if (!NT_STATUS_IS_OK(status)) {
1665 TALLOC_FREE(subreq);
1669 protnum = SVAL(vwv, 0);
1671 if ((protnum >= ARRAY_SIZE(prots))
1672 || (prots[protnum].prot > cli->protocol)) {
1673 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1677 cli->protocol = prots[protnum].prot;
1679 if ((cli->protocol < PROTOCOL_NT1) &&
1680 client_is_signing_mandatory(cli)) {
1681 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1682 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1686 if (cli->protocol >= PROTOCOL_NT1) {
1688 bool negotiated_smb_signing = false;
1691 cli->sec_mode = CVAL(vwv + 1, 0);
1692 cli->max_mux = SVAL(vwv + 1, 1);
1693 cli->max_xmit = IVAL(vwv + 3, 1);
1694 cli->sesskey = IVAL(vwv + 7, 1);
1695 cli->serverzone = SVALS(vwv + 15, 1);
1696 cli->serverzone *= 60;
1697 /* this time arrives in real GMT */
1698 ts = interpret_long_date(((char *)(vwv+11))+1);
1699 cli->servertime = ts.tv_sec;
1700 cli->secblob = data_blob(bytes, num_bytes);
1701 cli->capabilities = IVAL(vwv + 9, 1);
1702 if (cli->capabilities & CAP_RAW_MODE) {
1703 cli->readbraw_supported = True;
1704 cli->writebraw_supported = True;
1706 /* work out if they sent us a workgroup */
1707 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1708 smb_buflen(cli->inbuf) > 8) {
1709 clistr_pull(cli->inbuf, cli->server_domain,
1710 bytes+8, sizeof(cli->server_domain),
1712 STR_UNICODE|STR_NOALIGN);
1716 * As signing is slow we only turn it on if either the client or
1717 * the server require it. JRA.
1720 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
1721 /* Fail if server says signing is mandatory and we don't want to support it. */
1722 if (!client_is_signing_allowed(cli)) {
1723 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1724 tevent_req_nterror(req,
1725 NT_STATUS_ACCESS_DENIED);
1728 negotiated_smb_signing = true;
1729 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
1730 /* Fail if client says signing is mandatory and the server doesn't support it. */
1731 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
1732 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1733 tevent_req_nterror(req,
1734 NT_STATUS_ACCESS_DENIED);
1737 negotiated_smb_signing = true;
1738 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
1739 negotiated_smb_signing = true;
1742 if (negotiated_smb_signing) {
1743 cli_set_signing_negotiated(cli);
1746 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
1747 SAFE_FREE(cli->outbuf);
1748 SAFE_FREE(cli->inbuf);
1749 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1750 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1751 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
1754 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1755 cli->use_spnego = False;
1756 cli->sec_mode = SVAL(vwv + 1, 0);
1757 cli->max_xmit = SVAL(vwv + 2, 0);
1758 cli->max_mux = SVAL(vwv + 3, 0);
1759 cli->sesskey = IVAL(vwv + 6, 0);
1760 cli->serverzone = SVALS(vwv + 10, 0);
1761 cli->serverzone *= 60;
1762 /* this time is converted to GMT by make_unix_date */
1763 cli->servertime = cli_make_unix_date(
1764 cli, (char *)(vwv + 8));
1765 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
1766 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
1767 cli->secblob = data_blob(bytes, num_bytes);
1769 /* the old core protocol */
1770 cli->use_spnego = False;
1772 cli->serverzone = get_time_zone(time(NULL));
1775 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1777 /* a way to force ascii SMB */
1778 if (getenv("CLI_FORCE_ASCII"))
1779 cli->capabilities &= ~CAP_UNICODE;
1781 tevent_req_done(req);
1784 NTSTATUS cli_negprot_recv(struct tevent_req *req)
1786 return tevent_req_simple_recv_ntstatus(req);
1789 NTSTATUS cli_negprot(struct cli_state *cli)
1791 TALLOC_CTX *frame = talloc_stackframe();
1792 struct event_context *ev;
1793 struct tevent_req *req;
1794 NTSTATUS status = NT_STATUS_OK;
1796 if (cli_has_async_calls(cli)) {
1798 * Can't use sync call while an async call is in flight
1800 status = NT_STATUS_INVALID_PARAMETER;
1804 ev = event_context_init(frame);
1806 status = NT_STATUS_NO_MEMORY;
1810 req = cli_negprot_send(frame, ev, cli);
1812 status = NT_STATUS_NO_MEMORY;
1816 if (!tevent_req_poll(req, ev)) {
1817 status = map_nt_error_from_unix(errno);
1821 status = cli_negprot_recv(req);
1824 if (!NT_STATUS_IS_OK(status)) {
1825 cli_set_error(cli, status);
1830 /****************************************************************************
1831 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1832 ****************************************************************************/
1834 bool cli_session_request(struct cli_state *cli,
1835 struct nmb_name *calling, struct nmb_name *called)
1841 /* 445 doesn't have session request */
1842 if (cli->port == 445)
1845 memcpy(&(cli->calling), calling, sizeof(*calling));
1846 memcpy(&(cli->called ), called , sizeof(*called ));
1848 /* put in the destination name */
1850 tmp = name_mangle(talloc_tos(), cli->called.name,
1851 cli->called.name_type);
1856 p = cli->outbuf+len;
1857 memcpy(p, tmp, name_len(tmp));
1858 len += name_len(tmp);
1863 tmp = name_mangle(talloc_tos(), cli->calling.name,
1864 cli->calling.name_type);
1869 p = cli->outbuf+len;
1870 memcpy(p, tmp, name_len(tmp));
1871 len += name_len(tmp);
1874 /* send a session request (RFC 1002) */
1875 /* setup the packet length
1876 * Remove four bytes from the length count, since the length
1877 * field in the NBT Session Service header counts the number
1878 * of bytes which follow. The cli_send_smb() function knows
1879 * about this and accounts for those four bytes.
1883 _smb_setlen(cli->outbuf,len);
1884 SCVAL(cli->outbuf,0,0x81);
1887 DEBUG(5,("Sent session request\n"));
1889 if (!cli_receive_smb(cli))
1892 if (CVAL(cli->inbuf,0) == 0x84) {
1893 /* C. Hoch 9/14/95 Start */
1894 /* For information, here is the response structure.
1895 * We do the byte-twiddling to for portability.
1896 struct RetargetResponse{
1898 unsigned char flags;
1904 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1905 struct in_addr dest_ip;
1908 /* SESSION RETARGET */
1909 putip((char *)&dest_ip,cli->inbuf+4);
1910 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
1912 status = open_socket_out(&cli->dest_ss, port,
1913 LONG_CONNECT_TIMEOUT, &cli->fd);
1914 if (!NT_STATUS_IS_OK(status)) {
1918 DEBUG(3,("Retargeted\n"));
1920 set_socket_options(cli->fd, lp_socket_options());
1927 DEBUG(0,("Retarget recursion - failing\n"));
1931 ret = cli_session_request(cli, calling, called);
1935 } /* C. Hoch 9/14/95 End */
1937 if (CVAL(cli->inbuf,0) != 0x82) {
1938 /* This is the wrong place to put the error... JRA. */
1939 cli->rap_error = CVAL(cli->inbuf,4);
1949 static void smb_sock_connected(struct tevent_req *req)
1951 struct fd_struct *pfd = tevent_req_callback_data(
1952 req, struct fd_struct);
1956 status = open_socket_out_defer_recv(req, &fd);
1957 if (NT_STATUS_IS_OK(status)) {
1962 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
1963 uint16_t *port, int timeout, int *pfd)
1965 struct event_context *ev;
1966 struct tevent_req *r139, *r445;
1967 struct fd_struct *fd139, *fd445;
1968 NTSTATUS status = NT_STATUS_NO_MEMORY;
1971 return open_socket_out(pss, *port, timeout, pfd);
1974 ev = event_context_init(talloc_tos());
1976 return NT_STATUS_NO_MEMORY;
1979 fd139 = talloc(ev, struct fd_struct);
1980 if (fd139 == NULL) {
1985 fd445 = talloc(ev, struct fd_struct);
1986 if (fd445 == NULL) {
1991 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
1993 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
1995 if ((r445 == NULL) || (r139 == NULL)) {
1998 tevent_req_set_callback(r445, smb_sock_connected, fd445);
1999 tevent_req_set_callback(r139, smb_sock_connected, fd139);
2001 while ((fd445->fd == -1) && (fd139->fd == -1)
2002 && (tevent_req_is_in_progress(r139)
2003 || tevent_req_is_in_progress(r445))) {
2004 event_loop_once(ev);
2007 if ((fd139->fd != -1) && (fd445->fd != -1)) {
2012 if (fd445->fd != -1) {
2015 status = NT_STATUS_OK;
2018 if (fd139->fd != -1) {
2021 status = NT_STATUS_OK;
2025 status = open_socket_out_defer_recv(r445, &fd445->fd);
2031 /****************************************************************************
2032 Open the client sockets.
2033 ****************************************************************************/
2035 NTSTATUS cli_connect(struct cli_state *cli,
2037 struct sockaddr_storage *dest_ss)
2040 int name_type = 0x20;
2041 TALLOC_CTX *frame = talloc_stackframe();
2042 unsigned int num_addrs = 0;
2044 struct sockaddr_storage *ss_arr = NULL;
2047 /* reasonable default hostname */
2049 host = STAR_SMBSERVER;
2052 fstrcpy(cli->desthost, host);
2054 /* allow hostnames of the form NAME#xx and do a netbios lookup */
2055 if ((p = strchr(cli->desthost, '#'))) {
2056 name_type = strtol(p+1, NULL, 16);
2060 if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
2061 NTSTATUS status =resolve_name_list(frame,
2066 if (!NT_STATUS_IS_OK(status)) {
2068 return NT_STATUS_BAD_NETWORK_NAME;
2072 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
2075 return NT_STATUS_NO_MEMORY;
2080 for (i = 0; i < num_addrs; i++) {
2081 cli->dest_ss = ss_arr[i];
2082 if (getenv("LIBSMB_PROG")) {
2083 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
2085 uint16_t port = cli->port;
2087 status = open_smb_socket(&cli->dest_ss, &port,
2088 cli->timeout, &cli->fd);
2089 if (NT_STATUS_IS_OK(status)) {
2093 if (cli->fd == -1) {
2094 char addr[INET6_ADDRSTRLEN];
2095 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
2096 DEBUG(2,("Error connecting to %s (%s)\n",
2097 dest_ss?addr:host,strerror(errno)));
2099 /* Exit from loop on first connection. */
2104 if (cli->fd == -1) {
2106 return map_nt_error_from_unix(errno);
2110 *dest_ss = cli->dest_ss;
2113 set_socket_options(cli->fd, lp_socket_options());
2116 return NT_STATUS_OK;
2120 establishes a connection to after the negprot.
2121 @param output_cli A fully initialised cli structure, non-null only on success
2122 @param dest_host The netbios name of the remote host
2123 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2124 @param port (optional) The destination port (0 for default)
2125 @param retry bool. Did this connection fail with a retryable error ?
2128 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2129 const char *my_name,
2130 const char *dest_host,
2131 struct sockaddr_storage *dest_ss, int port,
2132 int signing_state, int flags,
2136 struct nmb_name calling;
2137 struct nmb_name called;
2138 struct cli_state *cli;
2139 struct sockaddr_storage ss;
2145 my_name = global_myname();
2147 if (!(cli = cli_initialise_ex(signing_state))) {
2148 return NT_STATUS_NO_MEMORY;
2151 make_nmb_name(&calling, my_name, 0x0);
2152 make_nmb_name(&called , dest_host, 0x20);
2154 cli_set_port(cli, port);
2155 cli_set_timeout(cli, 10000); /* 10 seconds. */
2165 DEBUG(3,("Connecting to host=%s\n", dest_host));
2167 nt_status = cli_connect(cli, dest_host, &ss);
2168 if (!NT_STATUS_IS_OK(nt_status)) {
2169 char addr[INET6_ADDRSTRLEN];
2170 print_sockaddr(addr, sizeof(addr), &ss);
2171 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
2172 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
2180 if (!cli_session_request(cli, &calling, &called)) {
2182 DEBUG(1,("session request to %s failed (%s)\n",
2183 called.name, cli_errstr(cli)));
2184 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
2188 if (strcmp(called.name, STAR_SMBSERVER)) {
2189 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
2192 return NT_STATUS_BAD_NETWORK_NAME;
2195 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2196 cli->use_spnego = False;
2197 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2198 cli->use_kerberos = True;
2200 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2201 cli->use_kerberos) {
2202 cli->fallback_after_kerberos = true;
2205 nt_status = cli_negprot(cli);
2206 if (!NT_STATUS_IS_OK(nt_status)) {
2207 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2213 return NT_STATUS_OK;
2218 establishes a connection right up to doing tconX, password specified.
2219 @param output_cli A fully initialised cli structure, non-null only on success
2220 @param dest_host The netbios name of the remote host
2221 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2222 @param port (optional) The destination port (0 for default)
2223 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2224 @param service_type The 'type' of serivice.
2225 @param user Username, unix string
2226 @param domain User's domain
2227 @param password User's password, unencrypted unix string.
2228 @param retry bool. Did this connection fail with a retryable error ?
2231 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2232 const char *my_name,
2233 const char *dest_host,
2234 struct sockaddr_storage *dest_ss, int port,
2235 const char *service, const char *service_type,
2236 const char *user, const char *domain,
2237 const char *password, int flags,
2242 struct cli_state *cli = NULL;
2243 int pw_len = password ? strlen(password)+1 : 0;
2247 if (password == NULL) {
2251 nt_status = cli_start_connection(&cli, my_name, dest_host,
2252 dest_ss, port, signing_state,
2255 if (!NT_STATUS_IS_OK(nt_status)) {
2259 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
2260 cli->use_level_II_oplocks =
2261 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
2263 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2265 if (!NT_STATUS_IS_OK(nt_status)) {
2267 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2268 DEBUG(1,("failed session setup with %s\n",
2269 nt_errstr(nt_status)));
2274 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2275 if (!NT_STATUS_IS_OK(nt_status)) {
2276 DEBUG(1,("anonymous failed session setup with %s\n",
2277 nt_errstr(nt_status)));
2284 nt_status = cli_tcon_andx(cli, service, service_type, password,
2286 if (!NT_STATUS_IS_OK(nt_status)) {
2287 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2289 if (NT_STATUS_IS_OK(nt_status)) {
2290 nt_status = NT_STATUS_UNSUCCESSFUL;
2296 nt_status = cli_init_creds(cli, user, domain, password);
2297 if (!NT_STATUS_IS_OK(nt_status)) {
2303 return NT_STATUS_OK;
2306 /****************************************************************************
2307 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2308 ****************************************************************************/
2310 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
2311 struct sockaddr_storage *pdest_ss)
2313 struct nmb_name calling, called;
2315 make_nmb_name(&calling, srchost, 0x0);
2318 * If the called name is an IP address
2319 * then use *SMBSERVER immediately.
2322 if(is_ipaddress(desthost)) {
2323 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
2325 make_nmb_name(&called, desthost, 0x20);
2328 if (!cli_session_request(*ppcli, &calling, &called)) {
2330 struct nmb_name smbservername;
2332 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2335 * If the name wasn't *SMBSERVER then
2336 * try with *SMBSERVER if the first name fails.
2339 if (nmb_name_equal(&called, &smbservername)) {
2342 * The name used was *SMBSERVER, don't bother with another name.
2345 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2346 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2351 cli_shutdown(*ppcli);
2353 *ppcli = cli_initialise();
2355 /* Out of memory... */
2359 status = cli_connect(*ppcli, desthost, pdest_ss);
2360 if (!NT_STATUS_IS_OK(status) ||
2361 !cli_session_request(*ppcli, &calling, &smbservername)) {
2362 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2363 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2371 /****************************************************************************
2372 Send an old style tcon.
2373 ****************************************************************************/
2374 NTSTATUS cli_raw_tcon(struct cli_state *cli,
2375 const char *service, const char *pass, const char *dev,
2376 uint16 *max_xmit, uint16 *tid)
2380 if (!lp_client_plaintext_auth() && (*pass)) {
2381 DEBUG(1, ("Server requested plaintext password but 'client "
2382 "plaintext auth' is disabled\n"));
2383 return NT_STATUS_ACCESS_DENIED;
2386 memset(cli->outbuf,'\0',smb_size);
2387 memset(cli->inbuf,'\0',smb_size);
2389 cli_set_message(cli->outbuf, 0, 0, True);
2390 SCVAL(cli->outbuf,smb_com,SMBtcon);
2391 cli_setup_packet(cli);
2393 p = smb_buf(cli->outbuf);
2394 *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
2395 *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
2396 *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
2398 cli_setup_bcc(cli, p);
2401 if (!cli_receive_smb(cli)) {
2402 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2405 if (cli_is_error(cli)) {
2406 return cli_nt_error(cli);
2409 *max_xmit = SVAL(cli->inbuf, smb_vwv0);
2410 *tid = SVAL(cli->inbuf, smb_vwv1);
2412 return NT_STATUS_OK;
2415 /* Return a cli_state pointing at the IPC$ share for the given server */
2417 struct cli_state *get_ipc_connect(char *server,
2418 struct sockaddr_storage *server_ss,
2419 const struct user_auth_info *user_info)
2421 struct cli_state *cli;
2423 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2425 if (user_info->use_kerberos) {
2426 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2429 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
2430 user_info->username ? user_info->username : "",
2432 user_info->password ? user_info->password : "",
2436 if (NT_STATUS_IS_OK(nt_status)) {
2438 } else if (is_ipaddress(server)) {
2439 /* windows 9* needs a correct NMB name for connections */
2440 fstring remote_name;
2442 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2443 cli = get_ipc_connect(remote_name, server_ss, user_info);
2452 * Given the IP address of a master browser on the network, return its
2453 * workgroup and connect to it.
2455 * This function is provided to allow additional processing beyond what
2456 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2457 * browsers and obtain each master browsers' list of domains (in case the
2458 * first master browser is recently on the network and has not yet
2459 * synchronized with other master browsers and therefore does not yet have the
2460 * entire network browse list)
2463 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2464 struct ip_service *mb_ip,
2465 const struct user_auth_info *user_info,
2466 char **pp_workgroup_out)
2468 char addr[INET6_ADDRSTRLEN];
2470 struct cli_state *cli;
2471 struct sockaddr_storage server_ss;
2473 *pp_workgroup_out = NULL;
2475 print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2476 DEBUG(99, ("Looking up name of master browser %s\n",
2480 * Do a name status query to find out the name of the master browser.
2481 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2482 * master browser will not respond to a wildcard query (or, at least,
2483 * an NT4 server acting as the domain master browser will not).
2485 * We might be able to use ONLY the query on MSBROWSE, but that's not
2486 * yet been tested with all Windows versions, so until it is, leave
2487 * the original wildcard query as the first choice and fall back to
2488 * MSBROWSE if the wildcard query fails.
2490 if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2491 !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2493 DEBUG(99, ("Could not retrieve name status for %s\n",
2498 if (!find_master_ip(name, &server_ss)) {
2499 DEBUG(99, ("Could not find master ip for %s\n", name));
2503 *pp_workgroup_out = talloc_strdup(ctx, name);
2505 DEBUG(4, ("found master browser %s, %s\n", name, addr));
2507 print_sockaddr(addr, sizeof(addr), &server_ss);
2508 cli = get_ipc_connect(addr, &server_ss, user_info);
2514 * Return the IP address and workgroup of a master browser on the network, and
2518 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2519 const struct user_auth_info *user_info,
2520 char **pp_workgroup_out)
2522 struct ip_service *ip_list;
2523 struct cli_state *cli;
2526 *pp_workgroup_out = NULL;
2528 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2530 /* Go looking for workgroups by broadcasting on the local network */
2532 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2534 DEBUG(99, ("No master browsers responded\n"));
2538 for (i = 0; i < count; i++) {
2539 char addr[INET6_ADDRSTRLEN];
2540 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2541 DEBUG(99, ("Found master browser %s\n", addr));
2543 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2544 user_info, pp_workgroup_out);