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++) {
1013 DEBUG(3,("got OID=%s\n", OIDs[i]));
1014 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1015 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1016 cli->got_kerberos_mechanism = True;
1018 talloc_free(OIDs[i]);
1021 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1023 status = cli_set_username(cli, user);
1024 if (!NT_STATUS_IS_OK(status)) {
1025 return ADS_ERROR_NT(status);
1029 /* If password is set we reauthenticate to kerberos server
1030 * and do not store results */
1032 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1035 if (pass && *pass) {
1038 use_in_memory_ccache();
1039 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1042 TALLOC_FREE(principal);
1043 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1044 if (cli->fallback_after_kerberos)
1046 return ADS_ERROR_KRB5(ret);
1050 /* If we get a bad principal, try to guess it if
1051 we have a valid host NetBIOS name.
1053 if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1054 TALLOC_FREE(principal);
1057 if (principal == NULL &&
1058 !is_ipaddress(cli->desthost) &&
1059 !strequal(STAR_SMBSERVER,
1062 char *machine = NULL;
1064 DEBUG(3,("cli_session_setup_spnego: got a "
1065 "bad server principal, trying to guess ...\n"));
1067 host = strchr_m(cli->desthost, '.');
1069 machine = SMB_STRNDUP(cli->desthost,
1070 host - cli->desthost);
1072 machine = SMB_STRDUP(cli->desthost);
1074 if (machine == NULL) {
1075 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1079 realm = SMB_STRDUP(dest_realm);
1082 realm = kerberos_get_default_realm_from_ccache();
1084 if (realm && *realm) {
1085 principal = talloc_asprintf(NULL, "%s$@%s",
1090 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1092 DEBUG(3,("cli_session_setup_spnego: guessed "
1093 "server principal=%s\n",
1094 principal ? principal : "<null>"));
1101 rc = cli_session_setup_kerberos(cli, principal,
1103 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1104 TALLOC_FREE(principal);
1111 TALLOC_FREE(principal);
1115 account = talloc_strdup(talloc_tos(), user);
1117 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1120 /* when falling back to ntlmssp while authenticating with a machine
1121 * account strip off the realm - gd */
1123 if ((p = strchr_m(user, '@')) != NULL) {
1124 account[PTR_DIFF(p,user)] = '\0';
1127 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1130 /****************************************************************************
1131 Send a session setup. The username and workgroup is in UNIX character
1132 format and must be converted to DOS codepage format before sending. If the
1133 password is in plaintext, the same should be done.
1134 ****************************************************************************/
1136 NTSTATUS cli_session_setup(struct cli_state *cli,
1138 const char *pass, int passlen,
1139 const char *ntpass, int ntpasslen,
1140 const char *workgroup)
1146 fstrcpy(user2, user);
1155 /* allow for workgroups as part of the username */
1156 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1157 (p=strchr_m(user2,*lp_winbind_separator()))) {
1163 if (cli->protocol < PROTOCOL_LANMAN1) {
1164 return NT_STATUS_OK;
1167 /* now work out what sort of session setup we are going to
1168 do. I have split this into separate functions to make the
1169 flow a bit easier to understand (tridge) */
1171 /* if its an older server then we have to use the older request format */
1173 if (cli->protocol < PROTOCOL_NT1) {
1174 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1175 DEBUG(1, ("Server requested LM password but 'client lanman auth'"
1177 return NT_STATUS_ACCESS_DENIED;
1180 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1181 !lp_client_plaintext_auth() && (*pass)) {
1182 DEBUG(1, ("Server requested plaintext password but "
1183 "'client plaintext auth' is disabled\n"));
1184 return NT_STATUS_ACCESS_DENIED;
1187 return cli_session_setup_lanman2(cli, user, pass, passlen,
1191 /* if no user is supplied then we have to do an anonymous connection.
1192 passwords are ignored */
1194 if (!user || !*user)
1195 return cli_session_setup_guest(cli);
1197 /* if the server is share level then send a plaintext null
1198 password at this point. The password is sent in the tree
1201 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
1202 return cli_session_setup_plaintext(cli, user, "", workgroup);
1204 /* if the server doesn't support encryption then we have to use
1205 plaintext. The second password is ignored */
1207 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1208 if (!lp_client_plaintext_auth() && (*pass)) {
1209 DEBUG(1, ("Server requested plaintext password but "
1210 "'client plaintext auth' is disabled\n"));
1211 return NT_STATUS_ACCESS_DENIED;
1213 return cli_session_setup_plaintext(cli, user, pass, workgroup);
1216 /* if the server supports extended security then use SPNEGO */
1218 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
1219 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
1221 if (!ADS_ERR_OK(status)) {
1222 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1223 return ads_ntstatus(status);
1228 /* otherwise do a NT1 style session setup */
1229 status = cli_session_setup_nt1(cli, user, pass, passlen,
1230 ntpass, ntpasslen, workgroup);
1231 if (!NT_STATUS_IS_OK(status)) {
1232 DEBUG(3,("cli_session_setup: NT1 session setup "
1233 "failed: %s\n", nt_errstr(status)));
1238 if (strstr(cli->server_type, "Samba")) {
1239 cli->is_samba = True;
1242 return NT_STATUS_OK;
1245 /****************************************************************************
1247 *****************************************************************************/
1249 bool cli_ulogoff(struct cli_state *cli)
1251 memset(cli->outbuf,'\0',smb_size);
1252 cli_set_message(cli->outbuf,2,0,True);
1253 SCVAL(cli->outbuf,smb_com,SMBulogoffX);
1254 cli_setup_packet(cli);
1255 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1256 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1259 if (!cli_receive_smb(cli))
1262 if (cli_is_error(cli)) {
1270 /****************************************************************************
1272 ****************************************************************************/
1274 struct cli_tcon_andx_state {
1275 struct cli_state *cli;
1280 static void cli_tcon_andx_done(struct tevent_req *subreq);
1282 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1283 struct event_context *ev,
1284 struct cli_state *cli,
1285 const char *share, const char *dev,
1286 const char *pass, int passlen,
1287 struct tevent_req **psmbreq)
1289 struct tevent_req *req, *subreq;
1290 struct cli_tcon_andx_state *state;
1296 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1303 fstrcpy(cli->share, share);
1305 /* in user level security don't send a password now */
1306 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1309 } else if (pass == NULL) {
1310 DEBUG(1, ("Server not using user level security and no "
1311 "password supplied.\n"));
1315 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1316 *pass && passlen != 24) {
1317 if (!lp_client_lanman_auth()) {
1318 DEBUG(1, ("Server requested LANMAN password "
1319 "(share-level security) but "
1320 "'client lanman auth' is disabled\n"));
1325 * Non-encrypted passwords - convert to DOS codepage before
1329 SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
1331 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1332 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1334 if (!lp_client_plaintext_auth() && (*pass)) {
1335 DEBUG(1, ("Server requested plaintext "
1336 "password but 'client plaintext "
1337 "auth' is disabled\n"));
1342 * Non-encrypted passwords - convert to DOS codepage
1345 passlen = clistr_push(cli, pword, pass, sizeof(pword),
1347 if (passlen == -1) {
1348 DEBUG(1, ("clistr_push(pword) failed\n"));
1353 memcpy(pword, pass, passlen);
1358 SCVAL(vwv+0, 0, 0xFF);
1361 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
1362 SSVAL(vwv+3, 0, passlen);
1365 bytes = (uint8_t *)talloc_memdup(state, pword, passlen);
1367 bytes = talloc_array(state, uint8_t, 0);
1373 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1374 cli->desthost, share);
1379 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
1384 * Add the devicetype
1386 tmp = talloc_strdup_upper(talloc_tos(), dev);
1391 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1394 if (bytes == NULL) {
1399 state->bytes.iov_base = (void *)bytes;
1400 state->bytes.iov_len = talloc_get_size(bytes);
1402 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
1404 if (subreq == NULL) {
1408 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
1413 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1414 return tevent_req_post(req, ev);
1417 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
1418 struct event_context *ev,
1419 struct cli_state *cli,
1420 const char *share, const char *dev,
1421 const char *pass, int passlen)
1423 struct tevent_req *req, *subreq;
1426 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
1431 status = cli_smb_req_send(subreq);
1432 if (!NT_STATUS_IS_OK(status)) {
1433 tevent_req_nterror(req, status);
1434 return tevent_req_post(req, ev);
1439 static void cli_tcon_andx_done(struct tevent_req *subreq)
1441 struct tevent_req *req = tevent_req_callback_data(
1442 subreq, struct tevent_req);
1443 struct cli_tcon_andx_state *state = tevent_req_data(
1444 req, struct cli_tcon_andx_state);
1445 struct cli_state *cli = state->cli;
1446 char *inbuf = (char *)cli_smb_inbuf(subreq);
1453 status = cli_smb_recv(subreq, 0, &wct, &vwv, &num_bytes, &bytes);
1454 if (!NT_STATUS_IS_OK(status)) {
1455 TALLOC_FREE(subreq);
1456 tevent_req_nterror(req, status);
1460 clistr_pull(inbuf, cli->dev, bytes, sizeof(fstring), num_bytes,
1461 STR_TERMINATE|STR_ASCII);
1463 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
1464 /* almost certainly win95 - enable bug fixes */
1469 * Make sure that we have the optional support 16-bit field. WCT > 2.
1470 * Avoids issues when connecting to Win9x boxes sharing files
1473 cli->dfsroot = false;
1475 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
1476 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
1479 cli->cnum = SVAL(inbuf,smb_tid);
1480 tevent_req_done(req);
1483 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
1485 return tevent_req_simple_recv_ntstatus(req);
1488 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
1489 const char *dev, const char *pass, int passlen)
1491 TALLOC_CTX *frame = talloc_stackframe();
1492 struct event_context *ev;
1493 struct tevent_req *req;
1494 NTSTATUS status = NT_STATUS_OK;
1496 if (cli_has_async_calls(cli)) {
1498 * Can't use sync call while an async call is in flight
1500 status = NT_STATUS_INVALID_PARAMETER;
1504 ev = event_context_init(frame);
1506 status = NT_STATUS_NO_MEMORY;
1510 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
1512 status = NT_STATUS_NO_MEMORY;
1516 if (!tevent_req_poll(req, ev)) {
1517 status = map_nt_error_from_unix(errno);
1521 status = cli_tcon_andx_recv(req);
1524 if (!NT_STATUS_IS_OK(status)) {
1525 cli_set_error(cli, status);
1530 /****************************************************************************
1531 Send a tree disconnect.
1532 ****************************************************************************/
1534 bool cli_tdis(struct cli_state *cli)
1536 memset(cli->outbuf,'\0',smb_size);
1537 cli_set_message(cli->outbuf,0,0,True);
1538 SCVAL(cli->outbuf,smb_com,SMBtdis);
1539 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1540 cli_setup_packet(cli);
1543 if (!cli_receive_smb(cli))
1546 if (cli_is_error(cli)) {
1554 /****************************************************************************
1555 Send a negprot command.
1556 ****************************************************************************/
1558 void cli_negprot_sendsync(struct cli_state *cli)
1563 if (cli->protocol < PROTOCOL_NT1)
1564 cli->use_spnego = False;
1566 memset(cli->outbuf,'\0',smb_size);
1568 /* setup the protocol strings */
1569 cli_set_message(cli->outbuf,0,0,True);
1571 p = smb_buf(cli->outbuf);
1572 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1573 if (prots[numprots].prot > cli->protocol) {
1577 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1580 SCVAL(cli->outbuf,smb_com,SMBnegprot);
1581 cli_setup_bcc(cli, p);
1582 cli_setup_packet(cli);
1584 SCVAL(smb_buf(cli->outbuf),0,2);
1589 /****************************************************************************
1590 Send a negprot command.
1591 ****************************************************************************/
1593 struct cli_negprot_state {
1594 struct cli_state *cli;
1597 static void cli_negprot_done(struct tevent_req *subreq);
1599 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
1600 struct event_context *ev,
1601 struct cli_state *cli)
1603 struct tevent_req *req, *subreq;
1604 struct cli_negprot_state *state;
1605 uint8_t *bytes = NULL;
1608 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
1614 if (cli->protocol < PROTOCOL_NT1)
1615 cli->use_spnego = False;
1617 /* setup the protocol strings */
1618 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1620 if (prots[numprots].prot > cli->protocol) {
1623 bytes = (uint8_t *)talloc_append_blob(
1624 state, bytes, data_blob_const(&c, sizeof(c)));
1625 if (tevent_req_nomem(bytes, req)) {
1626 return tevent_req_post(req, ev);
1628 bytes = smb_bytes_push_str(bytes, false,
1629 prots[numprots].name,
1630 strlen(prots[numprots].name)+1,
1632 if (tevent_req_nomem(bytes, req)) {
1633 return tevent_req_post(req, ev);
1637 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
1638 talloc_get_size(bytes), bytes);
1639 if (tevent_req_nomem(subreq, req)) {
1640 return tevent_req_post(req, ev);
1642 tevent_req_set_callback(subreq, cli_negprot_done, req);
1646 static void cli_negprot_done(struct tevent_req *subreq)
1648 struct tevent_req *req = tevent_req_callback_data(
1649 subreq, struct tevent_req);
1650 struct cli_negprot_state *state = tevent_req_data(
1651 req, struct cli_negprot_state);
1652 struct cli_state *cli = state->cli;
1660 status = cli_smb_recv(subreq, 1, &wct, &vwv, &num_bytes, &bytes);
1661 if (!NT_STATUS_IS_OK(status)) {
1662 TALLOC_FREE(subreq);
1666 protnum = SVAL(vwv, 0);
1668 if ((protnum >= ARRAY_SIZE(prots))
1669 || (prots[protnum].prot > cli->protocol)) {
1670 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1674 cli->protocol = prots[protnum].prot;
1676 if ((cli->protocol < PROTOCOL_NT1) &&
1677 client_is_signing_mandatory(cli)) {
1678 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1679 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1683 if (cli->protocol >= PROTOCOL_NT1) {
1685 bool negotiated_smb_signing = false;
1688 cli->sec_mode = CVAL(vwv + 1, 0);
1689 cli->max_mux = SVAL(vwv + 1, 1);
1690 cli->max_xmit = IVAL(vwv + 3, 1);
1691 cli->sesskey = IVAL(vwv + 7, 1);
1692 cli->serverzone = SVALS(vwv + 15, 1);
1693 cli->serverzone *= 60;
1694 /* this time arrives in real GMT */
1695 ts = interpret_long_date(((char *)(vwv+11))+1);
1696 cli->servertime = ts.tv_sec;
1697 cli->secblob = data_blob(bytes, num_bytes);
1698 cli->capabilities = IVAL(vwv + 9, 1);
1699 if (cli->capabilities & CAP_RAW_MODE) {
1700 cli->readbraw_supported = True;
1701 cli->writebraw_supported = True;
1703 /* work out if they sent us a workgroup */
1704 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1705 smb_buflen(cli->inbuf) > 8) {
1706 clistr_pull(cli->inbuf, cli->server_domain,
1707 bytes+8, sizeof(cli->server_domain),
1709 STR_UNICODE|STR_NOALIGN);
1713 * As signing is slow we only turn it on if either the client or
1714 * the server require it. JRA.
1717 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
1718 /* Fail if server says signing is mandatory and we don't want to support it. */
1719 if (!client_is_signing_allowed(cli)) {
1720 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1721 tevent_req_nterror(req,
1722 NT_STATUS_ACCESS_DENIED);
1725 negotiated_smb_signing = true;
1726 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
1727 /* Fail if client says signing is mandatory and the server doesn't support it. */
1728 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
1729 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1730 tevent_req_nterror(req,
1731 NT_STATUS_ACCESS_DENIED);
1734 negotiated_smb_signing = true;
1735 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
1736 negotiated_smb_signing = true;
1739 if (negotiated_smb_signing) {
1740 cli_set_signing_negotiated(cli);
1743 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
1744 SAFE_FREE(cli->outbuf);
1745 SAFE_FREE(cli->inbuf);
1746 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1747 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1748 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
1751 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1752 cli->use_spnego = False;
1753 cli->sec_mode = SVAL(vwv + 1, 0);
1754 cli->max_xmit = SVAL(vwv + 2, 0);
1755 cli->max_mux = SVAL(vwv + 3, 0);
1756 cli->sesskey = IVAL(vwv + 6, 0);
1757 cli->serverzone = SVALS(vwv + 10, 0);
1758 cli->serverzone *= 60;
1759 /* this time is converted to GMT by make_unix_date */
1760 cli->servertime = cli_make_unix_date(
1761 cli, (char *)(vwv + 8));
1762 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
1763 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
1764 cli->secblob = data_blob(bytes, num_bytes);
1766 /* the old core protocol */
1767 cli->use_spnego = False;
1769 cli->serverzone = get_time_zone(time(NULL));
1772 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1774 /* a way to force ascii SMB */
1775 if (getenv("CLI_FORCE_ASCII"))
1776 cli->capabilities &= ~CAP_UNICODE;
1778 tevent_req_done(req);
1781 NTSTATUS cli_negprot_recv(struct tevent_req *req)
1783 return tevent_req_simple_recv_ntstatus(req);
1786 NTSTATUS cli_negprot(struct cli_state *cli)
1788 TALLOC_CTX *frame = talloc_stackframe();
1789 struct event_context *ev;
1790 struct tevent_req *req;
1791 NTSTATUS status = NT_STATUS_OK;
1793 if (cli_has_async_calls(cli)) {
1795 * Can't use sync call while an async call is in flight
1797 status = NT_STATUS_INVALID_PARAMETER;
1801 ev = event_context_init(frame);
1803 status = NT_STATUS_NO_MEMORY;
1807 req = cli_negprot_send(frame, ev, cli);
1809 status = NT_STATUS_NO_MEMORY;
1813 if (!tevent_req_poll(req, ev)) {
1814 status = map_nt_error_from_unix(errno);
1818 status = cli_negprot_recv(req);
1821 if (!NT_STATUS_IS_OK(status)) {
1822 cli_set_error(cli, status);
1827 /****************************************************************************
1828 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1829 ****************************************************************************/
1831 bool cli_session_request(struct cli_state *cli,
1832 struct nmb_name *calling, struct nmb_name *called)
1838 /* 445 doesn't have session request */
1839 if (cli->port == 445)
1842 memcpy(&(cli->calling), calling, sizeof(*calling));
1843 memcpy(&(cli->called ), called , sizeof(*called ));
1845 /* put in the destination name */
1847 tmp = name_mangle(talloc_tos(), cli->called.name,
1848 cli->called.name_type);
1853 p = cli->outbuf+len;
1854 memcpy(p, tmp, name_len(tmp));
1855 len += name_len(tmp);
1860 tmp = name_mangle(talloc_tos(), cli->calling.name,
1861 cli->calling.name_type);
1866 p = cli->outbuf+len;
1867 memcpy(p, tmp, name_len(tmp));
1868 len += name_len(tmp);
1871 /* send a session request (RFC 1002) */
1872 /* setup the packet length
1873 * Remove four bytes from the length count, since the length
1874 * field in the NBT Session Service header counts the number
1875 * of bytes which follow. The cli_send_smb() function knows
1876 * about this and accounts for those four bytes.
1880 _smb_setlen(cli->outbuf,len);
1881 SCVAL(cli->outbuf,0,0x81);
1884 DEBUG(5,("Sent session request\n"));
1886 if (!cli_receive_smb(cli))
1889 if (CVAL(cli->inbuf,0) == 0x84) {
1890 /* C. Hoch 9/14/95 Start */
1891 /* For information, here is the response structure.
1892 * We do the byte-twiddling to for portability.
1893 struct RetargetResponse{
1895 unsigned char flags;
1901 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1902 struct in_addr dest_ip;
1905 /* SESSION RETARGET */
1906 putip((char *)&dest_ip,cli->inbuf+4);
1907 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
1909 status = open_socket_out(&cli->dest_ss, port,
1910 LONG_CONNECT_TIMEOUT, &cli->fd);
1911 if (!NT_STATUS_IS_OK(status)) {
1915 DEBUG(3,("Retargeted\n"));
1917 set_socket_options(cli->fd, lp_socket_options());
1924 DEBUG(0,("Retarget recursion - failing\n"));
1928 ret = cli_session_request(cli, calling, called);
1932 } /* C. Hoch 9/14/95 End */
1934 if (CVAL(cli->inbuf,0) != 0x82) {
1935 /* This is the wrong place to put the error... JRA. */
1936 cli->rap_error = CVAL(cli->inbuf,4);
1946 static void smb_sock_connected(struct tevent_req *req)
1948 struct fd_struct *pfd = tevent_req_callback_data(
1949 req, struct fd_struct);
1953 status = open_socket_out_defer_recv(req, &fd);
1954 if (NT_STATUS_IS_OK(status)) {
1959 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
1960 uint16_t *port, int timeout, int *pfd)
1962 struct event_context *ev;
1963 struct tevent_req *r139, *r445;
1964 struct fd_struct *fd139, *fd445;
1965 NTSTATUS status = NT_STATUS_NO_MEMORY;
1968 return open_socket_out(pss, *port, timeout, pfd);
1971 ev = event_context_init(talloc_tos());
1973 return NT_STATUS_NO_MEMORY;
1976 fd139 = talloc(ev, struct fd_struct);
1977 if (fd139 == NULL) {
1982 fd445 = talloc(ev, struct fd_struct);
1983 if (fd445 == NULL) {
1988 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
1990 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
1992 if ((r445 == NULL) || (r139 == NULL)) {
1995 tevent_req_set_callback(r445, smb_sock_connected, fd445);
1996 tevent_req_set_callback(r139, smb_sock_connected, fd139);
1998 while ((fd445->fd == -1) && (fd139->fd == -1)
1999 && (tevent_req_is_in_progress(r139)
2000 || tevent_req_is_in_progress(r445))) {
2001 event_loop_once(ev);
2004 if ((fd139->fd != -1) && (fd445->fd != -1)) {
2009 if (fd445->fd != -1) {
2012 status = NT_STATUS_OK;
2015 if (fd139->fd != -1) {
2018 status = NT_STATUS_OK;
2022 status = open_socket_out_defer_recv(r445, &fd445->fd);
2028 /****************************************************************************
2029 Open the client sockets.
2030 ****************************************************************************/
2032 NTSTATUS cli_connect(struct cli_state *cli,
2034 struct sockaddr_storage *dest_ss)
2037 int name_type = 0x20;
2038 TALLOC_CTX *frame = talloc_stackframe();
2039 unsigned int num_addrs = 0;
2041 struct sockaddr_storage *ss_arr = NULL;
2044 /* reasonable default hostname */
2046 host = STAR_SMBSERVER;
2049 fstrcpy(cli->desthost, host);
2051 /* allow hostnames of the form NAME#xx and do a netbios lookup */
2052 if ((p = strchr(cli->desthost, '#'))) {
2053 name_type = strtol(p+1, NULL, 16);
2057 if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
2058 NTSTATUS status =resolve_name_list(frame,
2063 if (!NT_STATUS_IS_OK(status)) {
2065 return NT_STATUS_BAD_NETWORK_NAME;
2069 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
2072 return NT_STATUS_NO_MEMORY;
2077 for (i = 0; i < num_addrs; i++) {
2078 cli->dest_ss = ss_arr[i];
2079 if (getenv("LIBSMB_PROG")) {
2080 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
2082 uint16_t port = cli->port;
2084 status = open_smb_socket(&cli->dest_ss, &port,
2085 cli->timeout, &cli->fd);
2086 if (NT_STATUS_IS_OK(status)) {
2090 if (cli->fd == -1) {
2091 char addr[INET6_ADDRSTRLEN];
2092 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
2093 DEBUG(2,("Error connecting to %s (%s)\n",
2094 dest_ss?addr:host,strerror(errno)));
2096 /* Exit from loop on first connection. */
2101 if (cli->fd == -1) {
2103 return map_nt_error_from_unix(errno);
2107 *dest_ss = cli->dest_ss;
2110 set_socket_options(cli->fd, lp_socket_options());
2113 return NT_STATUS_OK;
2117 establishes a connection to after the negprot.
2118 @param output_cli A fully initialised cli structure, non-null only on success
2119 @param dest_host The netbios name of the remote host
2120 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2121 @param port (optional) The destination port (0 for default)
2122 @param retry bool. Did this connection fail with a retryable error ?
2125 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2126 const char *my_name,
2127 const char *dest_host,
2128 struct sockaddr_storage *dest_ss, int port,
2129 int signing_state, int flags,
2133 struct nmb_name calling;
2134 struct nmb_name called;
2135 struct cli_state *cli;
2136 struct sockaddr_storage ss;
2142 my_name = global_myname();
2144 if (!(cli = cli_initialise_ex(signing_state))) {
2145 return NT_STATUS_NO_MEMORY;
2148 make_nmb_name(&calling, my_name, 0x0);
2149 make_nmb_name(&called , dest_host, 0x20);
2151 cli_set_port(cli, port);
2152 cli_set_timeout(cli, 10000); /* 10 seconds. */
2162 DEBUG(3,("Connecting to host=%s\n", dest_host));
2164 nt_status = cli_connect(cli, dest_host, &ss);
2165 if (!NT_STATUS_IS_OK(nt_status)) {
2166 char addr[INET6_ADDRSTRLEN];
2167 print_sockaddr(addr, sizeof(addr), &ss);
2168 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
2169 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
2177 if (!cli_session_request(cli, &calling, &called)) {
2179 DEBUG(1,("session request to %s failed (%s)\n",
2180 called.name, cli_errstr(cli)));
2181 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
2185 if (strcmp(called.name, STAR_SMBSERVER)) {
2186 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
2189 return NT_STATUS_BAD_NETWORK_NAME;
2192 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2193 cli->use_spnego = False;
2194 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2195 cli->use_kerberos = True;
2197 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2198 cli->use_kerberos) {
2199 cli->fallback_after_kerberos = true;
2202 nt_status = cli_negprot(cli);
2203 if (!NT_STATUS_IS_OK(nt_status)) {
2204 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2210 return NT_STATUS_OK;
2215 establishes a connection right up to doing tconX, password specified.
2216 @param output_cli A fully initialised cli structure, non-null only on success
2217 @param dest_host The netbios name of the remote host
2218 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2219 @param port (optional) The destination port (0 for default)
2220 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2221 @param service_type The 'type' of serivice.
2222 @param user Username, unix string
2223 @param domain User's domain
2224 @param password User's password, unencrypted unix string.
2225 @param retry bool. Did this connection fail with a retryable error ?
2228 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2229 const char *my_name,
2230 const char *dest_host,
2231 struct sockaddr_storage *dest_ss, int port,
2232 const char *service, const char *service_type,
2233 const char *user, const char *domain,
2234 const char *password, int flags,
2239 struct cli_state *cli = NULL;
2240 int pw_len = password ? strlen(password)+1 : 0;
2244 if (password == NULL) {
2248 nt_status = cli_start_connection(&cli, my_name, dest_host,
2249 dest_ss, port, signing_state,
2252 if (!NT_STATUS_IS_OK(nt_status)) {
2256 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
2257 cli->use_level_II_oplocks =
2258 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
2260 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2262 if (!NT_STATUS_IS_OK(nt_status)) {
2264 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2265 DEBUG(1,("failed session setup with %s\n",
2266 nt_errstr(nt_status)));
2271 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2272 if (!NT_STATUS_IS_OK(nt_status)) {
2273 DEBUG(1,("anonymous failed session setup with %s\n",
2274 nt_errstr(nt_status)));
2281 nt_status = cli_tcon_andx(cli, service, service_type, password,
2283 if (!NT_STATUS_IS_OK(nt_status)) {
2284 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2286 if (NT_STATUS_IS_OK(nt_status)) {
2287 nt_status = NT_STATUS_UNSUCCESSFUL;
2293 nt_status = cli_init_creds(cli, user, domain, password);
2294 if (!NT_STATUS_IS_OK(nt_status)) {
2300 return NT_STATUS_OK;
2303 /****************************************************************************
2304 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2305 ****************************************************************************/
2307 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
2308 struct sockaddr_storage *pdest_ss)
2310 struct nmb_name calling, called;
2312 make_nmb_name(&calling, srchost, 0x0);
2315 * If the called name is an IP address
2316 * then use *SMBSERVER immediately.
2319 if(is_ipaddress(desthost)) {
2320 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
2322 make_nmb_name(&called, desthost, 0x20);
2325 if (!cli_session_request(*ppcli, &calling, &called)) {
2327 struct nmb_name smbservername;
2329 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2332 * If the name wasn't *SMBSERVER then
2333 * try with *SMBSERVER if the first name fails.
2336 if (nmb_name_equal(&called, &smbservername)) {
2339 * The name used was *SMBSERVER, don't bother with another name.
2342 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2343 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2348 cli_shutdown(*ppcli);
2350 *ppcli = cli_initialise();
2352 /* Out of memory... */
2356 status = cli_connect(*ppcli, desthost, pdest_ss);
2357 if (!NT_STATUS_IS_OK(status) ||
2358 !cli_session_request(*ppcli, &calling, &smbservername)) {
2359 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2360 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2368 /****************************************************************************
2369 Send an old style tcon.
2370 ****************************************************************************/
2371 NTSTATUS cli_raw_tcon(struct cli_state *cli,
2372 const char *service, const char *pass, const char *dev,
2373 uint16 *max_xmit, uint16 *tid)
2377 if (!lp_client_plaintext_auth() && (*pass)) {
2378 DEBUG(1, ("Server requested plaintext password but 'client "
2379 "plaintext auth' is disabled\n"));
2380 return NT_STATUS_ACCESS_DENIED;
2383 memset(cli->outbuf,'\0',smb_size);
2384 memset(cli->inbuf,'\0',smb_size);
2386 cli_set_message(cli->outbuf, 0, 0, True);
2387 SCVAL(cli->outbuf,smb_com,SMBtcon);
2388 cli_setup_packet(cli);
2390 p = smb_buf(cli->outbuf);
2391 *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
2392 *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
2393 *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
2395 cli_setup_bcc(cli, p);
2398 if (!cli_receive_smb(cli)) {
2399 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2402 if (cli_is_error(cli)) {
2403 return cli_nt_error(cli);
2406 *max_xmit = SVAL(cli->inbuf, smb_vwv0);
2407 *tid = SVAL(cli->inbuf, smb_vwv1);
2409 return NT_STATUS_OK;
2412 /* Return a cli_state pointing at the IPC$ share for the given server */
2414 struct cli_state *get_ipc_connect(char *server,
2415 struct sockaddr_storage *server_ss,
2416 const struct user_auth_info *user_info)
2418 struct cli_state *cli;
2420 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2422 if (user_info->use_kerberos) {
2423 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2426 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
2427 user_info->username ? user_info->username : "",
2429 user_info->password ? user_info->password : "",
2433 if (NT_STATUS_IS_OK(nt_status)) {
2435 } else if (is_ipaddress(server)) {
2436 /* windows 9* needs a correct NMB name for connections */
2437 fstring remote_name;
2439 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2440 cli = get_ipc_connect(remote_name, server_ss, user_info);
2449 * Given the IP address of a master browser on the network, return its
2450 * workgroup and connect to it.
2452 * This function is provided to allow additional processing beyond what
2453 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2454 * browsers and obtain each master browsers' list of domains (in case the
2455 * first master browser is recently on the network and has not yet
2456 * synchronized with other master browsers and therefore does not yet have the
2457 * entire network browse list)
2460 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2461 struct ip_service *mb_ip,
2462 const struct user_auth_info *user_info,
2463 char **pp_workgroup_out)
2465 char addr[INET6_ADDRSTRLEN];
2467 struct cli_state *cli;
2468 struct sockaddr_storage server_ss;
2470 *pp_workgroup_out = NULL;
2472 print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2473 DEBUG(99, ("Looking up name of master browser %s\n",
2477 * Do a name status query to find out the name of the master browser.
2478 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2479 * master browser will not respond to a wildcard query (or, at least,
2480 * an NT4 server acting as the domain master browser will not).
2482 * We might be able to use ONLY the query on MSBROWSE, but that's not
2483 * yet been tested with all Windows versions, so until it is, leave
2484 * the original wildcard query as the first choice and fall back to
2485 * MSBROWSE if the wildcard query fails.
2487 if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2488 !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2490 DEBUG(99, ("Could not retrieve name status for %s\n",
2495 if (!find_master_ip(name, &server_ss)) {
2496 DEBUG(99, ("Could not find master ip for %s\n", name));
2500 *pp_workgroup_out = talloc_strdup(ctx, name);
2502 DEBUG(4, ("found master browser %s, %s\n", name, addr));
2504 print_sockaddr(addr, sizeof(addr), &server_ss);
2505 cli = get_ipc_connect(addr, &server_ss, user_info);
2511 * Return the IP address and workgroup of a master browser on the network, and
2515 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2516 const struct user_auth_info *user_info,
2517 char **pp_workgroup_out)
2519 struct ip_service *ip_list;
2520 struct cli_state *cli;
2523 *pp_workgroup_out = NULL;
2525 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2527 /* Go looking for workgroups by broadcasting on the local network */
2529 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2531 DEBUG(99, ("No master browsers responded\n"));
2535 for (i = 0; i < count; i++) {
2536 char addr[INET6_ADDRSTRLEN];
2537 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2538 DEBUG(99, ("Found master browser %s\n", addr));
2540 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2541 user_info, pp_workgroup_out);