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;
1612 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
1618 if (cli->protocol < PROTOCOL_NT1)
1619 cli->use_spnego = False;
1621 /* setup the protocol strings */
1622 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1624 if (prots[numprots].prot > cli->protocol) {
1627 bytes = (uint8_t *)talloc_append_blob(
1628 state, bytes, data_blob_const(&c, sizeof(c)));
1629 if (tevent_req_nomem(bytes, req)) {
1630 return tevent_req_post(req, ev);
1632 bytes = smb_bytes_push_str(bytes, false,
1633 prots[numprots].name,
1634 strlen(prots[numprots].name)+1,
1636 if (tevent_req_nomem(bytes, req)) {
1637 return tevent_req_post(req, ev);
1644 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
1645 talloc_get_size(bytes), bytes);
1648 if (tevent_req_nomem(subreq, req)) {
1649 return tevent_req_post(req, ev);
1651 tevent_req_set_callback(subreq, cli_negprot_done, req);
1655 static void cli_negprot_done(struct tevent_req *subreq)
1657 struct tevent_req *req = tevent_req_callback_data(
1658 subreq, struct tevent_req);
1659 struct cli_negprot_state *state = tevent_req_data(
1660 req, struct cli_negprot_state);
1661 struct cli_state *cli = state->cli;
1669 status = cli_smb_recv(subreq, 1, &wct, &vwv, &num_bytes, &bytes);
1670 if (!NT_STATUS_IS_OK(status)) {
1671 TALLOC_FREE(subreq);
1675 protnum = SVAL(vwv, 0);
1677 if ((protnum >= ARRAY_SIZE(prots))
1678 || (prots[protnum].prot > cli->protocol)) {
1679 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1683 cli->protocol = prots[protnum].prot;
1685 if ((cli->protocol < PROTOCOL_NT1) &&
1686 client_is_signing_mandatory(cli)) {
1687 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1688 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1692 if (cli->protocol >= PROTOCOL_NT1) {
1694 bool negotiated_smb_signing = false;
1697 cli->sec_mode = CVAL(vwv + 1, 0);
1698 cli->max_mux = SVAL(vwv + 1, 1);
1699 cli->max_xmit = IVAL(vwv + 3, 1);
1700 cli->sesskey = IVAL(vwv + 7, 1);
1701 cli->serverzone = SVALS(vwv + 15, 1);
1702 cli->serverzone *= 60;
1703 /* this time arrives in real GMT */
1704 ts = interpret_long_date(((char *)(vwv+11))+1);
1705 cli->servertime = ts.tv_sec;
1706 cli->secblob = data_blob(bytes, num_bytes);
1707 cli->capabilities = IVAL(vwv + 9, 1);
1708 if (cli->capabilities & CAP_RAW_MODE) {
1709 cli->readbraw_supported = True;
1710 cli->writebraw_supported = True;
1712 /* work out if they sent us a workgroup */
1713 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1714 smb_buflen(cli->inbuf) > 8) {
1715 clistr_pull(cli->inbuf, cli->server_domain,
1716 bytes+8, sizeof(cli->server_domain),
1718 STR_UNICODE|STR_NOALIGN);
1722 * As signing is slow we only turn it on if either the client or
1723 * the server require it. JRA.
1726 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
1727 /* Fail if server says signing is mandatory and we don't want to support it. */
1728 if (!client_is_signing_allowed(cli)) {
1729 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1730 tevent_req_nterror(req,
1731 NT_STATUS_ACCESS_DENIED);
1734 negotiated_smb_signing = true;
1735 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
1736 /* Fail if client says signing is mandatory and the server doesn't support it. */
1737 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
1738 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1739 tevent_req_nterror(req,
1740 NT_STATUS_ACCESS_DENIED);
1743 negotiated_smb_signing = true;
1744 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
1745 negotiated_smb_signing = true;
1748 if (negotiated_smb_signing) {
1749 cli_set_signing_negotiated(cli);
1752 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
1753 SAFE_FREE(cli->outbuf);
1754 SAFE_FREE(cli->inbuf);
1755 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1756 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1757 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
1760 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1761 cli->use_spnego = False;
1762 cli->sec_mode = SVAL(vwv + 1, 0);
1763 cli->max_xmit = SVAL(vwv + 2, 0);
1764 cli->max_mux = SVAL(vwv + 3, 0);
1765 cli->sesskey = IVAL(vwv + 6, 0);
1766 cli->serverzone = SVALS(vwv + 10, 0);
1767 cli->serverzone *= 60;
1768 /* this time is converted to GMT by make_unix_date */
1769 cli->servertime = cli_make_unix_date(
1770 cli, (char *)(vwv + 8));
1771 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
1772 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
1773 cli->secblob = data_blob(bytes, num_bytes);
1775 /* the old core protocol */
1776 cli->use_spnego = False;
1778 cli->serverzone = get_time_zone(time(NULL));
1781 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1783 /* a way to force ascii SMB */
1784 if (getenv("CLI_FORCE_ASCII"))
1785 cli->capabilities &= ~CAP_UNICODE;
1787 tevent_req_done(req);
1790 NTSTATUS cli_negprot_recv(struct tevent_req *req)
1792 return tevent_req_simple_recv_ntstatus(req);
1795 NTSTATUS cli_negprot(struct cli_state *cli)
1797 TALLOC_CTX *frame = talloc_stackframe();
1798 struct event_context *ev;
1799 struct tevent_req *req;
1800 NTSTATUS status = NT_STATUS_OK;
1802 if (cli_has_async_calls(cli)) {
1804 * Can't use sync call while an async call is in flight
1806 status = NT_STATUS_INVALID_PARAMETER;
1810 ev = event_context_init(frame);
1812 status = NT_STATUS_NO_MEMORY;
1816 req = cli_negprot_send(frame, ev, cli);
1818 status = NT_STATUS_NO_MEMORY;
1822 if (!tevent_req_poll(req, ev)) {
1823 status = map_nt_error_from_unix(errno);
1827 status = cli_negprot_recv(req);
1830 if (!NT_STATUS_IS_OK(status)) {
1831 cli_set_error(cli, status);
1836 /****************************************************************************
1837 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1838 ****************************************************************************/
1840 bool cli_session_request(struct cli_state *cli,
1841 struct nmb_name *calling, struct nmb_name *called)
1847 /* 445 doesn't have session request */
1848 if (cli->port == 445)
1851 memcpy(&(cli->calling), calling, sizeof(*calling));
1852 memcpy(&(cli->called ), called , sizeof(*called ));
1854 /* put in the destination name */
1856 tmp = name_mangle(talloc_tos(), cli->called.name,
1857 cli->called.name_type);
1862 p = cli->outbuf+len;
1863 memcpy(p, tmp, name_len(tmp));
1864 len += name_len(tmp);
1869 tmp = name_mangle(talloc_tos(), cli->calling.name,
1870 cli->calling.name_type);
1875 p = cli->outbuf+len;
1876 memcpy(p, tmp, name_len(tmp));
1877 len += name_len(tmp);
1880 /* send a session request (RFC 1002) */
1881 /* setup the packet length
1882 * Remove four bytes from the length count, since the length
1883 * field in the NBT Session Service header counts the number
1884 * of bytes which follow. The cli_send_smb() function knows
1885 * about this and accounts for those four bytes.
1889 _smb_setlen(cli->outbuf,len);
1890 SCVAL(cli->outbuf,0,0x81);
1893 DEBUG(5,("Sent session request\n"));
1895 if (!cli_receive_smb(cli))
1898 if (CVAL(cli->inbuf,0) == 0x84) {
1899 /* C. Hoch 9/14/95 Start */
1900 /* For information, here is the response structure.
1901 * We do the byte-twiddling to for portability.
1902 struct RetargetResponse{
1904 unsigned char flags;
1910 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1911 struct in_addr dest_ip;
1914 /* SESSION RETARGET */
1915 putip((char *)&dest_ip,cli->inbuf+4);
1916 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
1918 status = open_socket_out(&cli->dest_ss, port,
1919 LONG_CONNECT_TIMEOUT, &cli->fd);
1920 if (!NT_STATUS_IS_OK(status)) {
1924 DEBUG(3,("Retargeted\n"));
1926 set_socket_options(cli->fd, lp_socket_options());
1933 DEBUG(0,("Retarget recursion - failing\n"));
1937 ret = cli_session_request(cli, calling, called);
1941 } /* C. Hoch 9/14/95 End */
1943 if (CVAL(cli->inbuf,0) != 0x82) {
1944 /* This is the wrong place to put the error... JRA. */
1945 cli->rap_error = CVAL(cli->inbuf,4);
1955 static void smb_sock_connected(struct tevent_req *req)
1957 struct fd_struct *pfd = tevent_req_callback_data(
1958 req, struct fd_struct);
1962 status = open_socket_out_defer_recv(req, &fd);
1963 if (NT_STATUS_IS_OK(status)) {
1968 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
1969 uint16_t *port, int timeout, int *pfd)
1971 struct event_context *ev;
1972 struct tevent_req *r139, *r445;
1973 struct fd_struct *fd139, *fd445;
1974 NTSTATUS status = NT_STATUS_NO_MEMORY;
1977 return open_socket_out(pss, *port, timeout, pfd);
1980 ev = event_context_init(talloc_tos());
1982 return NT_STATUS_NO_MEMORY;
1985 fd139 = talloc(ev, struct fd_struct);
1986 if (fd139 == NULL) {
1991 fd445 = talloc(ev, struct fd_struct);
1992 if (fd445 == NULL) {
1997 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
1999 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
2001 if ((r445 == NULL) || (r139 == NULL)) {
2004 tevent_req_set_callback(r445, smb_sock_connected, fd445);
2005 tevent_req_set_callback(r139, smb_sock_connected, fd139);
2007 while ((fd445->fd == -1) && (fd139->fd == -1)
2008 && (tevent_req_is_in_progress(r139)
2009 || tevent_req_is_in_progress(r445))) {
2010 event_loop_once(ev);
2013 if ((fd139->fd != -1) && (fd445->fd != -1)) {
2018 if (fd445->fd != -1) {
2021 status = NT_STATUS_OK;
2024 if (fd139->fd != -1) {
2027 status = NT_STATUS_OK;
2031 status = open_socket_out_defer_recv(r445, &fd445->fd);
2037 /****************************************************************************
2038 Open the client sockets.
2039 ****************************************************************************/
2041 NTSTATUS cli_connect(struct cli_state *cli,
2043 struct sockaddr_storage *dest_ss)
2046 int name_type = 0x20;
2047 TALLOC_CTX *frame = talloc_stackframe();
2048 unsigned int num_addrs = 0;
2050 struct sockaddr_storage *ss_arr = NULL;
2053 /* reasonable default hostname */
2055 host = STAR_SMBSERVER;
2058 fstrcpy(cli->desthost, host);
2060 /* allow hostnames of the form NAME#xx and do a netbios lookup */
2061 if ((p = strchr(cli->desthost, '#'))) {
2062 name_type = strtol(p+1, NULL, 16);
2066 if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
2067 NTSTATUS status =resolve_name_list(frame,
2072 if (!NT_STATUS_IS_OK(status)) {
2074 return NT_STATUS_BAD_NETWORK_NAME;
2078 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
2081 return NT_STATUS_NO_MEMORY;
2086 for (i = 0; i < num_addrs; i++) {
2087 cli->dest_ss = ss_arr[i];
2088 if (getenv("LIBSMB_PROG")) {
2089 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
2091 uint16_t port = cli->port;
2093 status = open_smb_socket(&cli->dest_ss, &port,
2094 cli->timeout, &cli->fd);
2095 if (NT_STATUS_IS_OK(status)) {
2099 if (cli->fd == -1) {
2100 char addr[INET6_ADDRSTRLEN];
2101 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
2102 DEBUG(2,("Error connecting to %s (%s)\n",
2103 dest_ss?addr:host,strerror(errno)));
2105 /* Exit from loop on first connection. */
2110 if (cli->fd == -1) {
2112 return map_nt_error_from_unix(errno);
2116 *dest_ss = cli->dest_ss;
2119 set_socket_options(cli->fd, lp_socket_options());
2122 return NT_STATUS_OK;
2126 establishes a connection to after the negprot.
2127 @param output_cli A fully initialised cli structure, non-null only on success
2128 @param dest_host The netbios name of the remote host
2129 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2130 @param port (optional) The destination port (0 for default)
2131 @param retry bool. Did this connection fail with a retryable error ?
2134 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2135 const char *my_name,
2136 const char *dest_host,
2137 struct sockaddr_storage *dest_ss, int port,
2138 int signing_state, int flags,
2142 struct nmb_name calling;
2143 struct nmb_name called;
2144 struct cli_state *cli;
2145 struct sockaddr_storage ss;
2151 my_name = global_myname();
2153 if (!(cli = cli_initialise_ex(signing_state))) {
2154 return NT_STATUS_NO_MEMORY;
2157 make_nmb_name(&calling, my_name, 0x0);
2158 make_nmb_name(&called , dest_host, 0x20);
2160 cli_set_port(cli, port);
2161 cli_set_timeout(cli, 10000); /* 10 seconds. */
2171 DEBUG(3,("Connecting to host=%s\n", dest_host));
2173 nt_status = cli_connect(cli, dest_host, &ss);
2174 if (!NT_STATUS_IS_OK(nt_status)) {
2175 char addr[INET6_ADDRSTRLEN];
2176 print_sockaddr(addr, sizeof(addr), &ss);
2177 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
2178 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
2186 if (!cli_session_request(cli, &calling, &called)) {
2188 DEBUG(1,("session request to %s failed (%s)\n",
2189 called.name, cli_errstr(cli)));
2190 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
2194 if (strcmp(called.name, STAR_SMBSERVER)) {
2195 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
2198 return NT_STATUS_BAD_NETWORK_NAME;
2201 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2202 cli->use_spnego = False;
2203 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2204 cli->use_kerberos = True;
2206 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2207 cli->use_kerberos) {
2208 cli->fallback_after_kerberos = true;
2211 nt_status = cli_negprot(cli);
2212 if (!NT_STATUS_IS_OK(nt_status)) {
2213 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2219 return NT_STATUS_OK;
2224 establishes a connection right up to doing tconX, password specified.
2225 @param output_cli A fully initialised cli structure, non-null only on success
2226 @param dest_host The netbios name of the remote host
2227 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2228 @param port (optional) The destination port (0 for default)
2229 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2230 @param service_type The 'type' of serivice.
2231 @param user Username, unix string
2232 @param domain User's domain
2233 @param password User's password, unencrypted unix string.
2234 @param retry bool. Did this connection fail with a retryable error ?
2237 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2238 const char *my_name,
2239 const char *dest_host,
2240 struct sockaddr_storage *dest_ss, int port,
2241 const char *service, const char *service_type,
2242 const char *user, const char *domain,
2243 const char *password, int flags,
2248 struct cli_state *cli = NULL;
2249 int pw_len = password ? strlen(password)+1 : 0;
2253 if (password == NULL) {
2257 nt_status = cli_start_connection(&cli, my_name, dest_host,
2258 dest_ss, port, signing_state,
2261 if (!NT_STATUS_IS_OK(nt_status)) {
2265 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
2266 cli->use_level_II_oplocks =
2267 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
2269 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2271 if (!NT_STATUS_IS_OK(nt_status)) {
2273 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2274 DEBUG(1,("failed session setup with %s\n",
2275 nt_errstr(nt_status)));
2280 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2281 if (!NT_STATUS_IS_OK(nt_status)) {
2282 DEBUG(1,("anonymous failed session setup with %s\n",
2283 nt_errstr(nt_status)));
2290 nt_status = cli_tcon_andx(cli, service, service_type, password,
2292 if (!NT_STATUS_IS_OK(nt_status)) {
2293 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2295 if (NT_STATUS_IS_OK(nt_status)) {
2296 nt_status = NT_STATUS_UNSUCCESSFUL;
2302 nt_status = cli_init_creds(cli, user, domain, password);
2303 if (!NT_STATUS_IS_OK(nt_status)) {
2309 return NT_STATUS_OK;
2312 /****************************************************************************
2313 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2314 ****************************************************************************/
2316 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
2317 struct sockaddr_storage *pdest_ss)
2319 struct nmb_name calling, called;
2321 make_nmb_name(&calling, srchost, 0x0);
2324 * If the called name is an IP address
2325 * then use *SMBSERVER immediately.
2328 if(is_ipaddress(desthost)) {
2329 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
2331 make_nmb_name(&called, desthost, 0x20);
2334 if (!cli_session_request(*ppcli, &calling, &called)) {
2336 struct nmb_name smbservername;
2338 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2341 * If the name wasn't *SMBSERVER then
2342 * try with *SMBSERVER if the first name fails.
2345 if (nmb_name_equal(&called, &smbservername)) {
2348 * The name used was *SMBSERVER, don't bother with another name.
2351 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2352 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2357 cli_shutdown(*ppcli);
2359 *ppcli = cli_initialise();
2361 /* Out of memory... */
2365 status = cli_connect(*ppcli, desthost, pdest_ss);
2366 if (!NT_STATUS_IS_OK(status) ||
2367 !cli_session_request(*ppcli, &calling, &smbservername)) {
2368 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2369 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2377 /****************************************************************************
2378 Send an old style tcon.
2379 ****************************************************************************/
2380 NTSTATUS cli_raw_tcon(struct cli_state *cli,
2381 const char *service, const char *pass, const char *dev,
2382 uint16 *max_xmit, uint16 *tid)
2386 if (!lp_client_plaintext_auth() && (*pass)) {
2387 DEBUG(1, ("Server requested plaintext password but 'client "
2388 "plaintext auth' is disabled\n"));
2389 return NT_STATUS_ACCESS_DENIED;
2392 memset(cli->outbuf,'\0',smb_size);
2393 memset(cli->inbuf,'\0',smb_size);
2395 cli_set_message(cli->outbuf, 0, 0, True);
2396 SCVAL(cli->outbuf,smb_com,SMBtcon);
2397 cli_setup_packet(cli);
2399 p = smb_buf(cli->outbuf);
2400 *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
2401 *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
2402 *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
2404 cli_setup_bcc(cli, p);
2407 if (!cli_receive_smb(cli)) {
2408 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2411 if (cli_is_error(cli)) {
2412 return cli_nt_error(cli);
2415 *max_xmit = SVAL(cli->inbuf, smb_vwv0);
2416 *tid = SVAL(cli->inbuf, smb_vwv1);
2418 return NT_STATUS_OK;
2421 /* Return a cli_state pointing at the IPC$ share for the given server */
2423 struct cli_state *get_ipc_connect(char *server,
2424 struct sockaddr_storage *server_ss,
2425 const struct user_auth_info *user_info)
2427 struct cli_state *cli;
2429 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2431 if (user_info->use_kerberos) {
2432 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2435 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
2436 user_info->username ? user_info->username : "",
2438 user_info->password ? user_info->password : "",
2442 if (NT_STATUS_IS_OK(nt_status)) {
2444 } else if (is_ipaddress(server)) {
2445 /* windows 9* needs a correct NMB name for connections */
2446 fstring remote_name;
2448 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2449 cli = get_ipc_connect(remote_name, server_ss, user_info);
2458 * Given the IP address of a master browser on the network, return its
2459 * workgroup and connect to it.
2461 * This function is provided to allow additional processing beyond what
2462 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2463 * browsers and obtain each master browsers' list of domains (in case the
2464 * first master browser is recently on the network and has not yet
2465 * synchronized with other master browsers and therefore does not yet have the
2466 * entire network browse list)
2469 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2470 struct ip_service *mb_ip,
2471 const struct user_auth_info *user_info,
2472 char **pp_workgroup_out)
2474 char addr[INET6_ADDRSTRLEN];
2476 struct cli_state *cli;
2477 struct sockaddr_storage server_ss;
2479 *pp_workgroup_out = NULL;
2481 print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2482 DEBUG(99, ("Looking up name of master browser %s\n",
2486 * Do a name status query to find out the name of the master browser.
2487 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2488 * master browser will not respond to a wildcard query (or, at least,
2489 * an NT4 server acting as the domain master browser will not).
2491 * We might be able to use ONLY the query on MSBROWSE, but that's not
2492 * yet been tested with all Windows versions, so until it is, leave
2493 * the original wildcard query as the first choice and fall back to
2494 * MSBROWSE if the wildcard query fails.
2496 if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2497 !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2499 DEBUG(99, ("Could not retrieve name status for %s\n",
2504 if (!find_master_ip(name, &server_ss)) {
2505 DEBUG(99, ("Could not find master ip for %s\n", name));
2509 *pp_workgroup_out = talloc_strdup(ctx, name);
2511 DEBUG(4, ("found master browser %s, %s\n", name, addr));
2513 print_sockaddr(addr, sizeof(addr), &server_ss);
2514 cli = get_ipc_connect(addr, &server_ss, user_info);
2520 * Return the IP address and workgroup of a master browser on the network, and
2524 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2525 const struct user_auth_info *user_info,
2526 char **pp_workgroup_out)
2528 struct ip_service *ip_list;
2529 struct cli_state *cli;
2532 *pp_workgroup_out = NULL;
2534 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2536 /* Go looking for workgroups by broadcasting on the local network */
2538 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2540 DEBUG(99, ("No master browsers responded\n"));
2544 for (i = 0; i < count; i++) {
2545 char addr[INET6_ADDRSTRLEN];
2546 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2547 DEBUG(99, ("Found master browser %s\n", addr));
2549 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2550 user_info, pp_workgroup_out);